[[ condition ]]
使用and[ condition ]
或(( condition ))
and有什麼差別( condition )
?在什麼場景下我們需要使用其中任何一個?
(( 10 > 9 ))
有效但(( 10 -gt 9 ))
無效[[ 10 -gt 9 ]]
有效但[[ 10 > 9 ]]
無效
答案1
((...))
是外殼的算術構造。手冊中記錄了您可以使用的運算符:6.5 殼演算法
(...)
是一個分組在子 shell 中執行所包含指令的構造:3.2.4.3 分組命令
[...]
是「遺留」條件構造。文件位於6.4 Bash 條件表達式
[[...]]
做所有該[...]
做的事。不同之處在於,不會對內部變數執行分詞和全域擴展,[[...]]
因此引用變數並不那麼重要。另外,[[
還可以做模式匹配與==
操作員和正規表示式匹配與=~
操作員。
原因[[ 10 > 9 ]]
給你意想不到的結果是>
裡面的操作符[[...]]
是for字串比較且字串“10”“小於”字串“9”。
答案2
關於((…))
和(…)
如中所述這個另一個答案,((…))
是 shell 的算術結構(a巴什主義)並(…)
在子 shell 中執行命令。它們彼此之間以及與[ … ]
或 都非常不同[[ … ]]
。
另一方面,在簡單情況下[ … ]
和[[ … ]]
非常相似;他們可能會感到困惑。這個答案的其餘部分集中在[ … ]
和[[ … ]]
。
正式說明
我的目標是:
- 詳細說明
[ … ]
和之間的區別和相似之處[[ … ]]
; [ … ]
提供vs主題的規範答案,因此可以透過「不是」[[ … ]]
回答的問題可以連結到此處;[
[[
- 提供足夠詳盡的答案,因此用戶不再試圖發布只關注單一差異的答案。
什麼是[
?
[
執行測試。的目的
[
是測試某些內容(例如,是否存在某個文件),如果測試成功則返回退出狀態零,否則返回非零。[
是一個命令。[
是一個命令名稱,例如cat
或echo
。[
(如echo
) 是 Bash 中的內建命令,但這僅意味著它可以在不產生額外進程的情況下運行,它的行為仍然類似於命令。[
您的系統中可能有一個獨立的可執行檔(例如/bin/[
);試著type -a [
使用 Bash 來找出答案。[
後面需要一個空格。作為命令,
[
需要參數。與任何其他命令一樣,參數必須與另一個參數以及命令名稱分開。[foo
是一個不同的命令名稱,它不等於[ foo
(類似且更明顯的echoHello world
是不是echo Hello world
)。您當然需要在 後面有一個空格(或製表符)[
。[
需要]
.[
require]
作為最後一個參數,否則它將無法運作。這只是為了讓其[ … ]
作為一個塊脫穎而出,就好像它是某種特殊的語法一樣;但這不是特殊的語法。要]
作為最後一個參數傳遞,您需要在其前面有一個空格(或製表符)。為了比較:[ … bar]
is中的最後一個參數bar]
is not]
,所以[ … bar]
不是有效的指令。[
(幾乎)就像test
.[ … ]
相當於test …
.換句話說,您可以透過刪除並更改命令名稱來將任何[
命令轉換為命令。並且您可以透過更改命令名稱並添加.test
]
test
[
]
[
並不特別。最好記住
[
它並不特殊,它只是命令的一個有點奇特的名稱。如果您承認這一點,那麼您就不會對此感到驚訝全部shell 的解析與處理前如果命令是 ,也會發生運行命令(test
或echo
等) 。尤其:ls
[
[
不知道您是否引用了它的任何參數,它會在 shell 刪除引號後取得參數。未加引號且未轉義
&&
或||
介於[
and之間的]
內容不被解釋為 的參數[
。換句話說,[ … || … ]
被解釋為[ …
(無效,因為沒有]
)和… ]
(一個單獨的命令,無論…
是什麼)與 邏輯連接||
,完全相同command1 || command2
。
[
由 POSIX 指定。有的是POSIX 規範
[
/test
。您可以撥打[
手提電話。筆記:- 一些主要是擴展,一些被標記為過時。例如,我們的無效程式碼 (
[ … || … ]
) 可以修復為[ … -o … ]
,但由於-o
已過時,更好的修復方法是[ … ] || [ … ]
。 - 實現可能支持更多初選。
[
Bash 中的內建函數可以做到這一點(請參閱 參考資料)help test
;您的作業系統中的二進位檔案(如 )可能會(請參閱[
)。/bin/[
man test
- 一些主要是擴展,一些被標記為過時。例如,我們的無效程式碼 (
什麼是[[
?與有何[[
不同[
?
注意:
- 問題已標記巴什,現在我們正在談論[[
在重擊中。
- 本節編號的段落與上一節編號的段落相對應。
(相似)
[[
執行測試。的目的
[[
是測試某些內容(例如,是否存在某個文件),如果測試成功則返回退出狀態零,否則返回非零。[[
可以測試任何[
可以的東西,甚至更多。(不同之處)
[[
是一個關鍵字。是
[[
一個 shell 關鍵字(type [[
在 Bash 中呼叫以確認這一點)。與builtin一樣[
,該[[
關鍵字屬於Bash;但它才不是表現得像一個命令。(相似)
[[
後面需要一個空格。(或選項卡)。
(相似)
[[
需要]]
.[[
需要]]
稍後在程式碼中添加,但這不僅僅是為了使[[ … ]]
程式碼區塊脫穎而出。這是一種特殊的語法(有一個區別,我們會討論它)。之前需要一個空格(或製表符)]]
。(不同之處)不存在與 等效的普通命令
[[
。沒有其他命令/關鍵字/任何東西可以以可以替換的
[[
方式替換。test
[
(不同之處)
[[
是特別的。[[
改變 shell 解析和解釋程式碼的方式,直到匹配]]
. shell 在運作之前執行的正常解析和處理[
ortest
(或echo
等ls
)不適用於 inside[[ … ]]
。尤其:(不同之處)
[[
POSIX 沒有指定。不
[[
便於攜帶。[[
在 Bash 中工作,在 pure 中不起作用sh
。其他 shell 可能支援[[
(例如 Zsh),但它們可能與Bash[[
不同。[[
[[
未設計為符合[
/的規範test
。在許多情況下,替換[
with[[
和]
with]]
將為您提供[[ … ]]
與原始[ … ]
片段等效的片段;但不總是,有時內部需要調整。所以不要盲目[
改變[[
。盲目改成[[
風險[
更大,因為有些測試[[
可以做,有些測試[
不能做。
其他注意事項:
Nor
[
都不[[
是語法的一部分if … then …
。請記住,if
僅測試某些程式碼的退出狀態。if true; then …
有效、if sleep 5; then …
有效、類似if [ … ]; then …
或if [[ … ]]; then …
有效(如果[ … ]
或[[ … ]]
部分本身是有效片段)。由於
((…))
or(…)
也回傳一些退出狀態(這取決於內部內容),因此if
也可以在之後使用。就我個人而言,我更喜歡使用任何可以輕鬆完成的
[
測試,在真正必要時才使用。這樣我就不會習慣非可移植性,而且我知道我可以在不像 Bash 那樣豐富的 shell 中做什麼。[
[[
[[
作業系統中的可執行檔
[
不一定嚴格等同於[
Bash 中的內建檔案。如果[
由 Bash 調用,那麼內建函數將完成這項工作。如果[
被其他東西調用,那麼可執行檔將完成這項工作。例如find … -exec [ … ] …
使用可執行檔。沒有標準的[[
可執行檔(至少在我知道的系統中),所以find … -exec [[ … ]] …
永遠不會工作。如果有一個[[
可執行文件,那麼它的行為必須像命令一樣,它無法模仿關鍵字。
答案3
[ ] 與 [[ ]] 之間存在巨大差異:
a=0;
if [ $a = 1 -a $(grep ERR 1.log|wc -l) -ne 0 ];then
echo "error";
fi
使用 [ ] 時,and 運算子 -a 不支援短路評估。在上面的程式碼中,即使第一個條件回傳 false,第二個條件仍然會被評估。如果檔案1.log不存在,它會抱怨「沒有這樣的檔案或目錄」。
但對於 [[ ]]:
a=0
if [[ $a = 1 && $(grep ERR 1.log|wc -l) -ne 0 ];then
echo "error"
fi
即使檔案「1.log」不存在,也沒關係,因為第一個條件為假,所以不會評估第二個條件。
答案4
我本來可以將此放在評論中,但目前還不允許。
我注意到 [] 和 [[]] 之間的一個區別是,前者可以使用多重比較。
相同的比較會在 [[]] 中引發語法錯誤
a=1
b=2
這有效:
$ [ "$a" -gt 0 -a "$b" -gt "$a" ] && { echo '[b>a>0]'; }
[b>a>0]
這不起作用:
$ [[ $a -gt 0 -a $b -gt $a ]] && { echo '[[b>a>0]]'; }
-bash: syntax error in conditional expression
-bash: syntax error near `-a'
我還沒有真正深入了解為什麼會這樣,但在使用多重比較時,我使用 []。