轉 關於shell中if 語法結構的廣泛誤解

c3tc3tc3t發表於2014-01-03

轉自 ttp://blog.csdn.net/security134/article/details/6742156

最近學習SHELL程式設計 這篇文章很好很重要。有些東西不能想當然。同時不是表面看起來那麼簡單。以為自己懂了。其實差的還遠

 

 

Cuibtoy釋出於 2008-8-28 http://www.linuxdiyf.com/viewarticle.php?id=105505

我打賭正在看這篇文章的你, 超過99%的可能性你對這個問題的理解是錯的. 或者至少是有偏差的.

我深信這是一種教育法上的廣泛錯誤, 那就是告訴大家說:

if [ condition ]
then
...
fi

這是bash中條件語句的"語法".

任何人, 或者說幾乎任何人, 都會在這種描述下自然地認為: [ 和 ] 是這種語法結構本身的一部分, 並且, 老老實實地在自己的指令碼中總是這樣使用if 語句, 如果你總是在判斷字串是否相等, 或檔案的各種屬性, 這麼做倒是沒錯, 只不過你可能會這樣犯錯:(下文都假設$1內容為-a)

if ["$1" = "-a" ]

if [ "$1 = "-a"]

畢竟, 很多其它語言中, 特殊符號如()、{}做分隔符時, 可以與被分隔內容親密無間. 而bash會來答覆你的這種寫法:

[-a: command not found
bash: [: missing `]'

我相信, 以上這種心理模型造成的失敗後果十分嚴重, bash的錯誤資訊顯示出它內部並不這樣看待if 條件語句的結構.

上面的模型同樣不能解釋下面的合法bash 命令:

[ "$1" = "-a" ]

僅僅這本身就是一個合法的命令, 沒有if、then、fi這些東西,當然, 下面這樣的也合法

[ "$1" = "-a" ] && echo yes

你如何解釋這些爛事? 當然你可以自圓其說地不斷對上面的if進行補充, 呃, [ .. ] 這種結構就是這麼特別, 你必需在[之後有至少一個空格, 並且在]之前也至少有一個空格, 同時[..] 結構還可以單獨出現, 就象上面這樣, 另外... 這樣的解釋簡直是自欺欺人, 我敢保證企圖對自己這樣解釋的人根本自己就在懷疑這種說法, 因為你根本不知道這個結構還有其它什麼怪誕詭祕之處何時會突然跳出來讓你大吃一驚. 我承認,我自己也曾經經歷過這樣的想法.

為了徹底批判這種錯誤概念, 容我再舉一例:

if ps ax | grep oracle > /dev/null 2>&1 ; then
...
fi

首先, 這是合法的, 它的目的是想知道程式列表中有沒有與oracle相關的東西, 當然, 如果你夠牛, 就能看出這種做法有另外的問題. 但這不是我想說的重點.

我想說的是, 你前面被教導的這種if 語句的語法模型, 如何解釋這個, [ 與 ] 又不見了, 並且還出現了管道, 普通的管道我們都見過, 但它能安全地出現在if 語句中嗎, 並且, 讓你感覺熟悉和安全的[ 和 ]又不見了.

好吧, 撥亂的部分至此為止, 如果你想獲得一個關於bash中if結構的正確的健康的環保的知識, 就打起精神往下看:

1. 首先, [ 在bash中沒有特殊地位, 它是一個命令, 就跟cat, ls, grep一樣讓你感到熟悉的命令. 它不是關鍵字,雖然它的更出色的胞弟"[["是

echo [

你就得到 [, 不信就試試, bash不會報告任何錯誤! 但這不說明它不是關鍵字, echo if你也能得到if

所以, 請再試:

which [
以及
ls -l $(which [)

2. 然後, if 的真正模型是:

if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi

其實, bash中的help if就給了你正確的答案, 但我不知道什麼原因無數人就是忽略了它, 而非常多的bash教學資料中都採用了本文開頭提出的那種模型來告訴你關於if 結構的事.

注意: [ "$1" = "-a" ] 只一個命令, [ 是命令名!, "$1"是第一個引數, =是第二個引數, "-a"是第三個, ]是第4個. 是[這個命令, 而不是bash本身在報怨 [ "$1" = "-a"] 這樣的結構造成的錯誤, 因為[這個命令對它的引數有所期望, 它期望最後一個引數是 ], 而你用"-a"] 這種連寫的形式, 它得到的就只有3個引數: $1, = 和 -a].

這也解釋了這樣的錯誤:
["$1" = "-a" ]

bash直譯器得到了這樣的一個命令列:
[-a = "-a" ]

當然, 它認為 [-a 是命令名部分, 而你的系統中沒有這個命令, 所以會報告說:
[-a: command not found

3. 其次, bash中有一個builtin的 [命令, 通常你使用[執行的都是這個內建的命令, 目的是效率. 啟動一個程式的代價太高.

試試
type [
命令

相關文章