測試表達式中的參數擴展可能嗎?

測試表達式中的參數擴展可能嗎?

當我嘗試以下表達式時,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

請注意我如何使用[[...]]而不是[...]?雙括號條件對於空值較寬容。

相關內容