shell 比較中單等號 (=) 和雙等號 (=) 有何不同?

shell 比較中單等號 (=) 和雙等號 (=) 有何不同?

請閱讀,為了比較內部的字串,if我們需要使用雙方括號。有的書上說可以透過 來比較=。但它==也適用於。

#!/bin/bash
a="hello"
b="world"
if [[ $a == $b ]];then
    echo "equal"
fi

===比較有差嗎?

答案1

bash(就像從ksh哪裡bash複製該語法一樣),[[ $a == $b ]]不是比較,而是模式匹配。您需要[[ $a == "$b" ]]進行位元組到位元組的相等比較。===任何支援[[...]].

[[...]]不是標準sh語法。這[ 命令是標準,且標準比較存在運算符=(儘管某些[實作也可以識別==1)。

就像任何命令的任何參數一樣,必須引用變數擴展以防止分割+全域和空刪除(僅後者在 中執行zsh),所以:

[ "$a" = "$b" ]

在標準中sh,模式匹配是透過以下方式完成的case

case $a in
  ($b) ...
esac

為了完整起見,其他類似平等的您可能在 shell 腳本中遇到的運算子:

  • [ "$a" -eq "$b" ][比較十進制整數的標準運算子。有些[實作允許數字周圍有空格,有些允許任意算術表達式,但這不可移植。可移植地,人們可以使用[ "$(($a))" -eq "$(($b))" ]它。另請參閱[ "$((a == b))" -ne 0 ]以下標準等效項(POSIXly 除外,僅當$a$b包含整數常數時才指定行為):

  • ((a == b)),來自 ksh,也可在zsh和中找到bash,如果儲存在中的算術表達式的計算結果$a與 的結果相同,則傳回 true $b。通常,它用於比較數字。請注意,shell 之間在如何計算算術表達式以及支援哪些數字方面存在差異(例如 bash 和 ksh 的某些實作/版本不支援浮點或將帶前導零的數字視為八進位)。

  • expr "$a" = "$b"如果兩個運算元都被辨識為十進位整數(有些允許數字周圍有空格),則進行數字比較,否則檢查兩個字串運算元是否具有相同的排序順序。對於$a$bexpr運算符的值也會失敗(substr...

  • awk -- 'BEGIN{exit !(ARGV[1] == ARGV[2])}' "$a" "$b":如果$a$b被識別為數字(至少是十進制整數和浮點數,如 1.2、-1.5e-4,忽略前導尾隨空格,有些還識別十六進制、八進位或 識別的任何數字strtod()),則執行數字比較。否則,根據實現的不同,它要么是字節到字節的字串比較,要么是類似的expr比較strcoll(),即$a$b排序是否相同。

也可以看看:


1 包括 GNU[和, ,[的內建函數,雖然不是全部基於 shell 和,但請注意,kshbashyashashzshzsh=cmd是一個特殊的檔案名稱擴充運算符(在相同的上下文中擴展~user)擴展為相應命令的路徑,因此,除非您關閉equals禁用該功能的選項,否則您需要編寫它[ "$a" '==' "$b" ],否則您會收到錯誤,該=命令沒有找到。同樣適用於[ "$string" '=~' "$regexp" ]

答案2

這些在 bash 中是等效的:

[[ $x == "$y" ]]
[[ $x = "$y" ]]
[ "$x" == "$y" ]
[ "$x" = "$y" ]

前兩個 $x 變數不必加引號。 Bash 在 [ 內執行分詞和路徑名擴展,但不在 [[ 內執行:

$ x='a b'
$ [ -s $x ]
-bash: [: a: binary operator expected
$ [[ -s $x ]]
$ ls
$ [ a = * ]
-bash: [: a: unary operator expected
$ [[ a = * ]]
$ 

[[ $x = "$y" ]]是字串比較,但是[[ $x = $y ]]是模式比對表達式:

$ y='a*'; [[ aa = "$y" ]]; echo $?
1
$ y='a*'; [[ aa = $y ]]; echo $?
0

-eq 僅適用於整數:

$ [[ x.x -eq x.x ]]
-bash: [[: x.x: syntax error: invalid arithmetic operator (error token is ".x")
$ x=9; [[ "x" -eq 9 ]]; echo $?
0

也可以看看BashFAQ/031:測試、[ 和 [[ 之間有什麼區別?

答案3

=都是==運算符。在某些語言(如 C)中,一種用於為變數賦值,另一種用於比較值(算術表達式的結果)。事實上,這兩個運算子正是算術求值中的運算子。 A$((a=23))是賦值,a$((a==23))是算術比較。

$ echo "$((a=11)) $((a==23))" "$((a=23))" "$((a==23))"
11 0 23 1

但在測試結構內部(所有測試[…][[…]]) 兩個運算子的意思相同並執行相同的操作。

所以,所有這些選項:

test "$a" =  "$b"
   [ "$a" =  "$b" ]
  [[ "$a" =  "$b" ]]
test "$a" == "$b"
   [ "$a" == "$b" ]
  [[ "$a" == "$b" ]]

內部等效巴什測試二進制相等(引用的變數)。如果正確的變數未加引號,則它可能會被解釋為模式並進行相應的匹配:作為模式而不是文字字串。

帶有引號的運算子\=\==在 test 和 中使用時也是等效的[…]。但引用的運算符\==在內部失敗[[…]]

對於其他 shell,結果各不相同(正確的結果應該是Y -(true false),不同於 0 (true) 和 1 (false) 的退出代碼將報告為失敗¤)。某些 shell 會失敗- -(退出程式碼始終為 1)。

                     | dash  ksh   bash  zsh   
  test a  =  "$b"    | Y -   Y -   Y -   Y -    
     [ a  =  "$b" ]  | Y -   Y -   Y -   Y -    
    [[ a  =  "$b" ]] | ¤ ¤   Y -   Y -   Y -    
  test a  == "$b"    | ¤ ¤   Y -   Y -   - -    
     [ a  == "$b" ]  | ¤ ¤   Y -   Y -   - -    
    [[ a  == "$b" ]] | ¤ ¤   Y -   Y -   Y -    
  test a \=  "$b"    | Y -   Y -   Y -   Y -    
     [ a \=  "$b" ]  | Y -   Y -   Y -   Y -    
    [[ a \=  "$b" ]] | ¤ ¤   Y -   - -   - -    
  test a \== "$b"    | ¤ ¤   Y -   Y -   Y -    
     [ a \== "$b" ]  | ¤ ¤   Y -   Y -   Y -    
    [[ a \== "$b" ]] | ¤ ¤   Y -   - -   - -

所有選項都可以在 ksh 中使用,帶引號的運算子在 bash 和 zsh(在 內部[[…]])中失敗,而未加引號的運算\=\==在 zsh(在 外部[[…]])中也失敗。

相關內容