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

2021-06-16 10:40:57 字數 2615 閱讀 1688

我打賭正在看這篇文章的你, 超過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 [

命令幾乎所有的書都會講呀? [ ... ] 是呼叫test命令的特殊形式, 參考下面的命令。

$help [

[: [ arg... ]

this is a synonym for the "test" builtin, but the last

argument must be a literal `]', to match the opening `['.

$man test

name

test - check file types and compare values

synopsis

test expression

test

[ expression ]

[ ][ option

descriptio...

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

我打賭正在看這篇文章的你,超過99 的可能性你對這個問題的理解是錯的.或者至少是有偏差的.我深信這是一種教育法上的廣泛錯誤,那就是告訴大家說 if condition then fi 這是bash中條件語句的 語法 任何人,或者說幾乎任何人,都會在這種描述下自然地認為 和 是這種語法結構本身的一部分...

C 的語法結構

c 的語法結構包括 順序結構 分支結構 選擇結構 迴圈結構 順序結構 程式按照自上而下的順序,不發生跳躍地執行 分支結構 if 和 if else 符合哪個條件就執行哪個 塊 但是一般只有兩種選擇 選擇結構 if else if 和 switch case 符合哪個條件就執行哪個 塊 這個可以有更多...

jQuery的語法結構

一 jquery的語法結構 jquery語句主要包含三大部分 document和ready 分別被稱為工廠函式 選擇器 方法 語法 selector action 二 dom裡的節點通常分為3種型別 元素節點 文字節點 屬性節點 三 為dom元素新增樣式可以使用addclass 方法和css 方法 ...