测试表达式中的参数扩展可能吗?

测试表达式中的参数扩展可能吗?

当我尝试以下表达式时,bash我收到一条奇怪的错误消息:

[: -lt: unary operator expected

首先是函数定义

some_func () {
  (( 3 + 5 ))
}

和表达

[ $(some_func) -lt 10 ] && true

我想问题是混合运算符,例如-lt命令替换和/或算术扩展?

退出代码$?为 2,消息为an unary op was expected

答案1

它应该是

some_func() {
  echo "$(( 3 + 5 ))"
}
[ "$(some_func)" -lt 10 ]

为什么失败了

$(some_func)扩展到输出函数*(减去其尾随换行符),但是它什么也不输出。因此,测试变成

[ -lt 10 ]

在其最基本的形式中,[测试接受 1 到 3 个参数。由于上面有 2 个参数,Bash 期望第一个参数是一元运算符。-lt是二进制的,因此会出现错误消息。

有你吗适当引用扩展

[ "$(some_func)" -lt 10 ]

错误将是“预期的整数表达式”,因为测试将具有空字符串:

[ "" -lt 10 ]

并且,除非在不平凡的情况&& true是多余的。

*由于扩展未加引号,因此输出也会经历分词文件名扩展。尽管只要$IFS未更改其默认值,这些在本示例中不应发挥作用。

答案2

$(cmd)得到标准输出cmd,因此为了将其扩展到结果,您cmd需要输出它:

some_func() {
  echo "$(( 3 + 5 ))"
}
[ "$(some_func)" -lt 10 ]

正如其他人已经说过的。但是,这意味着some_func在子 shell 环境中运行,因此对变量或其他任何内容的任何修改都会在之后丢失。

例如,这样做是没有意义的:

counter=0
incr() { echo "$((++counter))"; }
while [ "$(incr)" -le 10 ]...

as$(incr)总是会扩展为 1(ascounter只会在子 shell 中递增)。

对于通过以下方式返回数值结果的函数算术评估,你需要一个支持的 shell数学函数喜欢ksh93zshbash不会的。

zsh

counter=0
incr() (( ++counter ))
functions -M incr

while (( incr() <= 10 )); do
  print $counter
done

ksh93

function .sh.math.incr i {
  # ksh93 functions must take at least one argument
  (( .sh.value = (counter += i) ))
}
while (( incr(1) <= 10 )); do
  print "$counter"
done

ksh93 或最新版本的 mksh 中的另一种替代方法是使用不引入子 shell 的命令替换形式:

counter=0
function incr { print "$(( ++counter ))"; }
while [ "${ incr; }" -le 10 ]; do
  print "$counter"
done

或者在mksh

counter=0
incr() (( REPLY = ++counter ))
while [ "${| incr; }" -le 10 ]; do
  print "$counter"
done

在任何 POSIX shell 中,包括bash,您始终可以返回预定义变量中的值($REPLY通常用于此目的):

counter=0
incr() { REPLY=$(( counter += 1 )); }
while incr; [ "$REPLY" -le 10 ]; do
  echo "$counter"
done

您可以在以下位置找到更多详细信息这是关于 mksh 的 valsub 功能的另一个问答的答案


¹ 剥离其尾随换行符,并且在bash其 NUL 字符的情况下,这里因为您忘记了引号,受 split+glob 约束

答案3

命令替换捕获输出命令或函数的。该函数没有输出。

$?变量保存的是返回码的函数。

要么这样做:

some_func
(( $? < 10 )) && echo yes

或将函数更改为:

some_func() {
    echo $(( 3 + 5 ))
}

[[ $(some_func) -lt 10 ]] && echo yes

请注意我如何使用[[...]]而不是[...]?双括号条件对于空值更加宽容。

相关内容