當我嘗試以下表達式時,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
請注意我如何使用[[...]]
而不是[...]
?雙括號條件對於空值較寬容。