[ vs [[ :在 bash 腳本中使用哪一個?
zsh 手冊頁的
test
(aka[
) 部分明確建議不要使用它,並敦促讀者盡可能使用[[
。相關部分指出:
該命令嘗試實現 POSIX 及其指定的擴展。不幸的是,語法中存在固有的歧義。特別是測試運算符和類似它們的字元串之間沒有區別。該標準試圖為少量參數(最多四個)解決這些問題;不能依賴五個或更多參數的兼容性。敦促使用者盡可能使用
[[
沒有這些歧義的 ’ ’ 測試語法。我想我遇到過關於 bash 的類似建議,但是當我瀏覽 bash 手冊頁時,我找不到任何關於使用哪種形式 (
[
或[[
) 的“官方”建議。(也許我錯過了?)除了向後兼容“舊外殼”之外,還有什麼理由可以
[
在 bash 腳本中使用?或者換一種說法,bash是否因為向後兼容性以外的原因而保持[
一致?[[
如果足夠的話,首選的原因
[
是不同的 bash 版本之間更穩定。[[``[
見
man bash
:兼容31
如果設置,bash 將其行為更改為 3.1 版的行為,以引用 [[ 條件命令的 =~ 運算符的參數。
兼容32
如果設置,則 bash 在使用 [[ 條件命令的 < 和 > 運算符時,將其行為更改為 3.2 版的行為,以進行特定於語言環境的字元串比較。bash-4.1 之前的 Bash 版本使用 ASCII 排序規則和 strcmp(3);bash-4.1 和更高版本使用目前語言環境的排序規則和 strcoll(3)。
兼容40
如果設置,則 bash 在使用 [[ 條件命令的 < 和 > 運算符(請參閱上一項)和中斷命令列表的效果時,將其行為更改為 4.0 版的行為,以進行特定於語言環境的字元串比較。
ksh
也許對於有背景的使用者來說也更常見一些。性能注意事項
‘[[’ 比 ‘[’ 更快
- 對於單個呼叫,速度差異沒有可比的影響,您應該更喜歡 ‘[’ 內置。
- 如果你在一個更大的循環結構中,你可能會想到用 ‘[[’ 替換 ‘[’
對於測量,您可以使用以下比較腳本
let upperBound=$1 echo "check [, ${upperBound} iterations" let i=0 time while [ $i -lt ${upperBound} ] ; do let i++ ; done echo; echo; echo "check [[, ${upperBound} iterations" let i=0 time while [[ $i < ${upperBound} ]] ; do let i++ ; done
比較腳本的結果
檢查 [, 1000 次迭代
真實 0m0.031s
使用者 0m0.028s
系統 0m0.004s
檢查 [[, 1000 次迭代
實際 0m0.000s
使用者 0m0.000s
系統 0m0.000s
雖然有一些細微的差別:
#!/bin/bash eg=whatever if [ $eg == what* ]; then # file glob test echo '[]' fi if [[ $eg == what* ]]; then # pattern match test echo "[[]]" fi
除非目前目錄中有一個名為“whatever”的文件,否則第一個測試不會通過,因為匹配是針對目前目錄內容的文件 glob,而第二個是實際的字元串模式匹配。