当我尝试以下表达式时,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
是多余的。
答案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数学函数喜欢ksh93
或zsh
。bash
不会的。
在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
请注意我如何使用[[...]]
而不是[...]
?双括号条件对于空值更加宽容。