Bash技巧:詳解test命令的參數個數不同對判斷結果的影響


Bash技巧:詳解test命令的參數個數不同對判斷結果的影響

在 Linux bash shell 中,使用 test 內置命令、[ 內置命令、和 [[ 內置命令進行判斷時,所提供的參數個數會影響判斷結果

下面以 test 命令為例介紹具體的影響,這些說明也適用於 [ 命令、[[ 命令。

查看 man bash 裡面對 test 命令不同參數個數的判斷結果說明如下:

test and [ evaluate conditional expressions using a set of rules

based on the number of arguments.


0 arguments

----The expression is false.

1 argument

----The expression is true if and only if the argument is not null.

2 arguments

----If the first argument is !, the expression is true if and only if

----the second argument is null. If the first argument is one of the

----unary conditional operators listed above under CONDITIONAL EXPRESSIONS,

----the expression is true if the unary test is true. If the first argument

----is not a valid unary conditional operator, the expression is false.

3 arguments

----The following conditions are applied in the order listed. If the second

----argument is one of the binary conditional operators listed above under

----CONDITIONAL EXPRESSIONS, the result of the expression is the result of

----the binary test using the first and third arguments as operands. If the

----first argument is !, the value is thenegation of the two-argument test

----using the second and third arguments.

針對不同的參數個數,具體舉例說明如下。

0 arguments

$ test; echo $?

1

這裡直接執行 test 命令,不提供任何參數。

參考上面 "0 arguments" 的說明,這種情況下的返回值總是 false。

用 echo $? 打印返回值為 1。

注意 test 命令把 1 作為 false。

1 argument

$ test -n; echo $?

0

$ test -z; echo $?

0

$ test -y; echo $?

0

$ set -x

$ test ""; echo $?;

+ test ''

+ echo 1

1

$ test $dummy; echo $?

+ test

+ echo 1

1

$ set +x

這裡單獨執行 test -n 和 test -z 這兩個命令。

用 echo $? 打印這兩個命令的返回值為 0,都是返回 true。

注意 test 命令把 0 作為 true。

參考上面 "1 argument" 的說明,只提供一個參數時,只要該參數不為空,就會返回 true。

此時的 -n 和 -z 被當作普通的字符串參數,沒被當作 test 命令的操作符。

可以看到執行 test -y 也是返回 true。但是 test 命令並不支持 -y 操作符。

在 help test 的說明中,test STRING 命令在 STRING 不為空時會返回 true,使用的就是隻提供一個參數時的判斷規則。

注意區分上面 test "" 和 test $dummy 的區別。

查看上面打印的調試信息,test "" 經過 bash 擴展,得到的結果是 test ''。

也就是確實有一個參數,這個參數是空字符串。

按照 "1 argument" 的說明,此時返回結果是 false。

由於沒有定義 dummy 變量,test $dummy 經過 bash 擴展,得到的結果只有 test,沒有提供參數。

按照 "0 arguments" 的說明,返回值為 false。

即,雖然 test "" 和 test $dummy 都返回 false,但是它們的參數個數不同,得出結果的原因也不同。

2 arguments

$ test -y go; echo $?

-bash: test: -y: unary operator expected

2

$ test -n go; echo $?

0

$ value=""; set -x

$ test ! -n $value; echo $?

+ test '!' -n

+ echo 1

1

$ test ! -n "$value"; echo $?

+ test '!' -n ''

+ echo 0

0

$ set +x

參考上面 "2 arguments" 的說明,提供兩個參數時,如果第一個參數不是 unary conditional operator,返回結果是 false。

由於 test 命令不支持 -y 操作符,執行 test -y go 命令報錯。

執行 test -n go 命令則會返回 -n 操作符對後面參數的判斷結果。

注意區分上面 test ! -n $value 和 test ! -n "$value" 的區別。

上面將 value 變量設成空字符串,test ! -n $value 經過 bash 擴展,得到的結果是 test '!' -n,提供了兩個參數。

按照 "2 arguments" 的說明,當第一個參數是 ! 時,只有第二個參數是空,才會返回 true。

這裡的第二個參數不是空,所以返回 false。

而 test ! -n "$value" 擴展後的結果是 test '!' -n '',提供了三個參數。

按照 "3 arguments" 說明的規則來進行判斷,會對後面兩個參數的判斷結果進行取反。這裡最終返回 true。

3 arguments

$ test -n go on

-bash: test: go: binary operator expected

在這個測試例子中,在 test -n 後面的字符串包含空格,又沒有用雙引號把字符串括起來,那麼參數個數會變多。

這裡提供了三個參數,-n 也是一個參數。

參考上面 "3 arguments" 的說明,提供三個參數時,預期第二個參數是 binary conditional operators。

由於這裡沒有提供,執行報錯,提示 "go: binary operator expected"。也就是所給的第二個參數 "go" 預期是一個 "binary operator",但它不是。

總結

總的來說,不加雙引號來引用變量值,當參數值為空、或者包含空格時,會導致 test 命令的參數個數發生變化。之後按照不同參數個數的判斷規則進行處理,可能會導致不預期的結果。

結合上面幾個例子可以看到,用雙引號把變量值括起來,只會得到一個參數,保持參數個數不變,可以避免很多異常。


分享到:


相關文章: