和其它編程語言類似,Shell 也支持兩種分支結構(選擇結構),分別是 if else 語句和 case in 語句。在《Shell if else》一節中我們講解了 if else 語句的用法,這節我們就來講解 case in 語句。
當分支較多,並且判斷條件比較簡單時,使用 case in 語句就比較方便了。
《Shell if else》一節的最后給出了一個例子,就是輸入一個整數,輸出該整數對應的星期幾的英文表示,這節我們就用 case in 語句來重寫代碼,如下所示。
- #!/bin/bash
- printf "Input integer number: "
- read num
- case $num in
- 1)
- echo "Monday"
- ;;
- 2)
- echo "Tuesday"
- ;;
- 3)
- echo "Wednesday"
- ;;
- 4)
- echo "Thursday"
- ;;
- 5)
- echo "Friday"
- ;;
- 6)
- echo "Saturday"
- ;;
- 7)
- echo "Sunday"
- ;;
- *)
- echo "error"
- esac
運行結果:
Input integer number:3↙
Wednesday
看了這個例子,相信大家對 case in 語句有了一個大體上的認識,那么,接下來我們就正式開始講解 case in 的用法,它的基本格式如下:
case expression in
pattern1)
statement1
;;
pattern2)
statement2
;;
pattern3)
statement3
;;
……
*)
statementn
esac
case、int 和 esac 都是 Shell 關鍵字,expression 表示表達式,pattern 表示匹配模式。
- expression 既可以是一個變量、一個數字、一個字符串,還可以是一個數學計算表達式,或者是命令的執行結果,只要能夠得到 expression 的值就可以。
- pattern 可以是一個數字、一個字符串,甚至是一個簡單的正則表達式。
case 會將 expression 的值與 pattern1、pattern2、pattern3 逐個進行匹配:
- 如果 expression 和某個模式(比如 pattern2)匹配成功,就會執行這模式(比如 pattern2)后面對應的所有語句(該語句可以有一條,也可以有多條),直到遇見雙分號
;;才停止;然后整個 case 語句就執行完了,程序會跳出整個 case 語句,執行 esac 后面的其它語句。 - 如果 expression 沒有匹配到任何一個模式,那么就執行
*)后面的語句(*表示其它所有值),直到遇見雙分號;;或者esac才結束。*)相當於多個 if 分支語句中最后的 else 部分。
如果你有 C語言、 C++、 Java 等編程經驗,這里的;;和*)就相當於其它編程語言中的 break 和 default。
對*)的幾點說明:
- Shell case in 語句中的
*)用來“托底”,萬一 expression 沒有匹配到任何一個模式,*)部分可以做一些“善后”工作,或者給用戶一些提示。 - 可以沒有
*)部分。如果 expression 沒有匹配到任何一個模式,那么就不執行任何操作。
除最后一個分支外(這個分支可以是普通分支,也可以是*)分支),其它的每個分支都必須以;;結尾,;;代表一個分支的結束,不寫的話會有語法錯誤。最后一個分支可以寫;;,也可以不寫,因為無論如何,執行到 esac 都會結束整個 case in 語句。
上面的代碼是 case in 最常見的用法,即 expression 部分是一個變量,pattern 部分是一個數字或者表達式。
case in 和正則表達式
case in 的 pattern 部分支持簡單的正則表達式,具體來說,可以使用以下幾種格式:
| 格式 | 說明 |
|---|---|
| * | 表示任意字符串。 |
| [abc] | 表示 a、b、c 三個字符中的任意一個。比如,[15ZH] 表示 1、5、Z、H 四個字符中的任意一個。 |
| [m-n] | 表示從 m 到 n 的任意一個字符。比如,[0-9] 表示任意一個數字,[0-9a-zA-Z] 表示字母或數字。 |
| | | 表示多重選擇,類似邏輯運算中的或運算。比如,abc | xyz 表示匹配字符串 "abc" 或者 "xyz"。 |
如果不加以說明,Shell 的值都是字符串,expression 和 pattern 也是按照字符串的方式來匹配的;本節第一段代碼看起來是判斷數字是否相等,其實是判斷字符串是否相等。
最后一個分支*)並不是什么語法規定,它只是一個正則表達式,*表示任意字符串,所以不管 expression 的值是什么,*)總能匹配成功。
下面的例子演示了如何在 case in 中使用正則表達式:
- #!/bin/bash
- printf "Input a character: "
- read -n 1 char
- case $char in
- [a-zA-Z])
- printf "\nletter\n"
- ;;
- [0-9])
- printf "\nDigit\n"
- ;;
- [0-9])
- printf "\nDigit\n"
- ;;
- [,.?!])
- printf "\nPunctuation\n"
- ;;
- *)
- printf "\nerror\n"
- esac
運行結果1:
Input integer number: S
letter
運行結果2:
Input integer number: ,
Punctuation
