Bash 沒有布林值的概念。 它只有字串和數字,以及由字串或數字組成的陣列。 那麼,條件指令又是如何看待 true 和 false 的呢?
指令在結束時會產生一個_退出狀態_。 退出狀態是一個 0 到 255(含)之間的整數。 Bash 認為退出狀態為零代表_成功_。 任何其他的退出狀態則代表_失敗_。
這適用於所有指令,包括 bash 內建指令、關鍵字和函式。
if 指令的基本語法如下
if CONDITIONAL_COMMANDS; then TRUE_COMMANDS; else FALSE_COMMANDS; fi
它從 if 開始,條件指令與「成功」指令之間以 then 分隔,並以 fi 結束。
else 子句是選用的。
CONDITIONAL_COMMANDS 可以是單一指令,也可以是一份指令清單。
CONDITIONAL_COMMANDS 會被執行,然後:
可以用 elif 串接多層分支
if CONDITIONAL_COMMANDS
then TRUE_COMMANDS
elif CONDITIONAL_COMMANDS_2
then TRUE_COMMANDS_2
# more elif branches ...
else FALSE_COMMANDS
fi
在 then、elif、else 和 fi 這些字之前,必須有一個分號或一個換行。
特別強調:控制流程走向的是條件指令的退出狀態。
舉例來說,grep 在找到符合的內容時回傳 0,找不到時回傳 1。
-q 選項會抑制輸出,只產生退出狀態。
if grep -q "my pattern" my_file; then echo "the pattern is found in the file"; fi
CONDITIONAL_COMMANDS 周圍並沒有什麼特殊語法。 你可能習慣看到像這樣的條件式:
if [ "$password" = "secure" ]; then
echo "Welcome!"
fi
[ 並不是特殊語法。
它是一個_指令_,用來評估條件運算式並以成功或失敗的狀態結束。
就像所有指令一樣,它與引數之間必須有空白。
[ 其實是 test 指令的同義詞。
兩者完全相同,差別只在於 [ 的最後一個引數_必須_是 ]。
在 [ 和 ] 之間,你要寫入一個條件運算式。
一些常見的條件運算式包括:
[ -f "$filename" ] # file operations
[ "$string1" = "$string2" ] # string comparisons
[ "$num1" -eq "$num2" ] # arithmetic comparisons
還有很多其他可用的運算;它們都列在手冊的 Bash 條件運算式 一節中。
在上面的範例中,請注意所有變數都加了引號。
test 和 [ 是普通的指令,它們的引數就像其他任何指令一樣,會受到單字分割與檔名展開的影響。
這一點值得特別說明,因為條件運算式會根據你提供_多少個引數_而有不同的評估方式:
[ -z "$name" ]),或是 !(用來反轉單一引數測試的狀態)如果忘記加引號,可能會得到意想不到的結果:
str=""
# this prints "empty"
if [ -n "$str" ]; then echo "not empty"; else echo "empty"; fi
# leaving the variable unquoted results in incorrect "not empty" output
if [ -n $str ]; then echo "not empty"; else echo "empty"; fi
[[...]] 條件結構 不是_指令_,而是關鍵字。
這表示,雖然它的處理方式和其他指令一樣,但它有特殊的剖析規則。
[[ 特別的地方在於,在其中展開的變數不會受到單字分割或檔名展開的影響。
這表示,即使不加引號,這個指令的行為也會如你所預期。
if [[ -n $str ]]; then echo "not empty"; else echo "empty"; fi
[[ 支援 test 和 [ 能處理的所有條件運算式。
除此之外,[[ 還提供
=~ 正規表示式比對運算子,== 和 != 可作為萬用字元模式的比對運算子,&& 和 || 可作為邏輯運算子(特殊剖析規則),< 和 > 可作為「直接」字串比較運算子(特殊剖析規則:因為它們是重導向符號,在 [ 中必須加以跳脫)。一般普遍認為,這些特殊功能帶來的好處太多,因此應該一律使用 [[。
(例如 Google Shell 風格指南。)
case 是另一種控制流程指令。
它就像其他語言中的「switch」敘述。
case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac
WORD 會逐一與每個 PATTERN 進行比對。 當其中一個符合時,就會執行對應的 COMMANDS。
read -p "Guess the secret word: " word
case "$word" in
secret) echo "Yes, you guessed it!" ;;
??????) echo "That's the right number of letters." ;;
s*) echo "You guessed the first letter." ;;
*) echo "Not even close! Try again." ;;
esac
每個 COMMANDS 子句都必須以兩個分號 ;; 結尾。