-- 作者 謝恩銘 轉載請註明出處
內容簡介
- 前言
- if : 最簡單的條件
- 條件測試
- case : 測試多個條件
- 總結
- 第五部分第五課預告
1. 前言
上一課 Linux探索之旅 | 第五部分第三課:變數在手,Shell不愁 有不少內容,這一課我們輕鬆一下,來聊聊條件語句。
有個對聯說得好:
「說你行,你就行,不行也行」
「說不行,就不行,行也不行」
「橫批:不服不行」
因此「條件一出,Shell 不服不行」。
讀者:小編你這是什麼邏輯?我們地球人表示不理解... 我看你還是回火星比較好。
小編:為了壓韻,也是蠻拼的...
對於所有程式語言,做決定是很重要的。如果程式設計師不決定程式做什麼,那麼程式只會一直做同樣的事情,就很無趣了。
而條件語句就是用於幫助程式做決定的。在我們的 Shell 指令碼中,條件語句可以做以下「抉擇」:
如果,變數的值等於 xxx ,
那麼,這樣做;
否則,那樣做。複製程式碼
如果你學過某一門程式語言,例如 C 語言 ( 歡迎學習我的 C語言探索之旅 ),那麼對於條件語句的原理應該很熟悉了。
即使你沒學過其他程式語言,那也不必擔心,跟著我們學完這課,保證你瞭然於胸。
2. if : 最簡單的條件
最常用的條件語句就是 if 條件語句。
if 是英語「如果」的意思。
if 條件語句的基本格式是這樣的:
if [ 條件測試 ]
then
做這個
fi複製程式碼
fi 是 if 的反轉寫法,表示「if 語句結束」。
then 是英語「那麼」的意思。
「做這個」只有在「條件測試」為真時,才會被執行。
注意:方括號 [] 中的「條件測試」兩邊必須要空一格。不能寫成 [test],而要寫成[ test ]。
唉,Shell 就是這麼任性,你不服都不行!
當然了,if 語句的基本寫法還有一種,那就是把 then 寫在 if [ 條件測試 ] 後面,如下:
if [ 條件測試 ]; then
做這個
fi複製程式碼
用這種寫法時,在 if 條件判斷和 then 之間要加一個分號。
我們寫 Shell 程式時,需要把「條件測試」換成我們真實要測試的條件,一般來說都是測試變數的值。
我們可以通過例子來學習,首先建立一個叫做 condition.sh 的檔案( condition 是英語「條件」的意思)。
vim condition.sh複製程式碼
然後在裡面輸入以下內容:
#!/bin/bash
name="Enming"
if [ $name = "Enming" ]
then
echo "Hello $name !"
fi複製程式碼
在 Shell 語言中,「等於」是用一個等號( = )來表示的,這和大多數主流程式語言不同。C語言中「等於」是用兩個等號( == )來表示的。但 Shell 中用兩個等號來表示「等於」的判斷也是可以的。
上例中,因為變數 name 的值等於 "Enming",因此會輸出 「Hello Enming !」
當然了,我們也可以測試兩個變數,例如:
#!/bin/bash
name1="Enming"
name2="Oscar"
if [ $name1 = $name2 ]
then
echo "You two have the same name !"
fi複製程式碼
「 You two have the same name 」是英語「你們倆有相同的名字」的意思。
執行上面的程式,可以看到什麼也沒有顯示,因為「 Enming 」和「 Oscar 」這兩個字串不相同。
else : 否則
既然有「如果」的條件判斷,那麼也會存在條件不成立的時候,就好比上面那個程式中,「 Enming 」和「 Oscar 」這兩個字串不相同的情況。
我們已經知道表示「如果」的關鍵字是 if,那麼表示「否則」的關鍵字應該就是 「else」咯?
沒錯。因為 else 就是英語「否則」的意思。
所以學好英語對於程式設計幫助極大:對於程式設計師, 為什麼英語比數學更重要? 如何學習 。
因此,if 和 else 兩者配合的邏輯是這樣的:
if [ 條件測試 ]
then
做這個
else
做那個
fi複製程式碼
也就是:如果「條件測試」為真,那麼「做這個」被執行;否則,「做那個」被執行。
我們來看一個例子:
#!/bin/bash
name1="Enming"
name2="Oscar"
if [ $name1 = $name2 ]
then
echo "You two have the same name !"
else
echo "You two have different name !"
fi複製程式碼
執行:
「 You two have different name 」是英語「你們有不同的名字」的意思。
elif : 否則,如果
一般來說 if 和 else 已經能滿足我們的大部分條件判斷需要了,但有些時候,存在好幾種情況。
光是 if 和 else 表示的兩種對立的情況已經不足以滿意要求了,因此我們再來學習一個關鍵字:elif 。
elif 是 「 else if 」的縮寫,表示「否則 - 如果」。
if, elif 和 else 三者配合的邏輯是這樣的:
if [ 條件測試 1 ]
then
做 1 的事情
elif [ 條件測試 2 ]
then
做 2 的事情
elif [ 條件測試 3 ]
then
做 3 的事情
else
做其他事情
fi複製程式碼
我們來看一個例子:
#!/bin/bash
if [ $1 = "Matthew" ]
then
echo "Hello Matthew !"
elif [ $1 = "Mark" ]
then
echo "Hello Mark !"
elif [ $1 = "Luke" ]
then
echo "Hello Luke !"
elif [ $1 = "John" ]
then
echo "Hello John !"
else
echo "Sorry, I do not know you."
fi複製程式碼
「 Sorry, I do not know you 」是英語「對不起,我不認識你」的意思。
執行:
我們可以寫任意多個 elif 語句,但是 if 語句必須要有且只能有一個,else 語句最多隻能有一個。
我們可以有單獨由 if 語句組成的條件語句,也可以有「 if ... else ... 」組成的條件語句,也可以有「 if ... elif ... else... 」組成的條件語句,也可以有「 if ... elif ... 」組成的語句。
3. 條件測試
現在我們來看看我們都能做哪些「條件測試」。
之前的例子,我們只比較了字串,但其實我們遠可以做比這更復雜的條件測試。
不同的測試型別
在 bash 中我們可以做三種測試:
- 測試字串
- 測試數字
- 測試檔案
我們通過例子一一來學習。
測試字串
我們之前的課程已經說過:在 Shell 中,所有的變數都是字串。
因此,要做字串的測試非常簡單。記住以下表格:
條件 | 意義 |
---|---|
$string1 = $string2 | 兩個字串是否相等。Shell 大小寫敏感,因此 A 和 a 是不一樣的。 |
$string1 != $string2 | 兩個字串是否不同。 |
-z $string | 字串 string 是否為空。z是 zero 的首字母,是英語「零」的意思。 |
-n $string | 字串 string 是否不為空。n 是英語 not 的首字母,是英語「不」的意思。 |
例如:
#!/bin/bash
if [ -z $1 ]
then
echo "No parameter"
else
echo "There is parameter"
fi複製程式碼
「 No parameter 」是英語「沒有引數」的意思。
「 There is parameter 」是英語「有引數」的意思。
測試數字
儘管 Shell 把所有變數都看成字串,但是我們還是可以做數字的條件測試。記住以下表格:
條件 | 意義 |
---|---|
$num1 -eq $num2 | 兩個數字是否相等。和判斷字串所用的符號( = )不一樣。eq 是 equal 的縮寫,是英語「等於」的意思。 |
$num1 -ne $num2 | 兩個數字是否不同。ne 是 not equal 的縮寫,是英語「不等於」的意思。 |
$num1 -lt $num2 | 數字 num1 是否小於 num2。lt 是 lower than 的縮寫,是英語「小於」的意思。 |
$num1 -le $num2 | 數字 num1 是否小於或等於 num2。le 是 lower or equal 的縮寫,是英語「小於或等於」的意思。 |
$num1 -gt $num2 | 數字 num1 是否大於 num2。gt 是 greater than 的縮寫,是英語「大於」的意思。 |
$num1 -ge $num2 | 數字 num1 是否大於或等於 num2。ge 是 greater or equal 的縮寫,是英語「大於或等於」的意思。 |
看一個例子:
#!/bin/bash
if [ $1 -ge 10 ]
then
echo "You have entered 10 or more"
else
echo "You have entered less than 10"
fi複製程式碼
「 You have entered 10 or more 」是英語「你的輸入等於 10 或比 10 更大」的意思。
「 You have entered less than 10 」是英語「你的輸入小於 10」的意思。
測試檔案
相比於主流程式語言,Shell 的一大優勢就是可以非常方便地測試檔案:檔案存在嗎?我們可以寫入檔案嗎?這個檔案比那個檔案修改時間更早還是更晚?等等。
下表非常豐富:
條件 | 意義 |
---|---|
-e $file | 檔案是否存在。e 是 exist 的首字母,表示「存在」。 |
-d $file | 檔案是否是一個目錄。因為 Linux 中所有都是檔案,目錄也是檔案的一種。d 是 directory 的首字母,表示「目錄」。 |
-f $file | 檔案是否是一個檔案。f 是 file 的首字母,表示「檔案」。 |
-L $file | 檔案是否是一個符號連結檔案。L 是 link 的首字母,表示「連結」。 |
-r $file | 檔案是否可讀。r 是 readable 的首字母,表示「可讀的」。 |
-w $file | 檔案是否可寫。w 是 writable 的首字母,表示「可寫的」。 |
-x $file | 檔案是否可執行。x 是 executable 的首字母,表示「可執行的」。 |
$file1 -nt $file2 | 檔案 file1 是否比 file2 更新。nt 是 newer than 的縮寫,表示「更新的」。 |
$file1 -ot $file2 | 檔案 file1 是否比 file2 更舊。ot 是 older than 的縮寫,表示「更舊的」。 |
來看一個例子:
#!/bin/bash
read -p 'Enter a directory : ' file
if [ -d $file ]
then
echo "$file is a directory"
else
echo "$file is not a directory"
fi複製程式碼
執行:
一次測試多個條件
在一個條件測試中,我們可以同時測試多個條件。需要用到兩種符號:
符號 | 意義 |
---|---|
&& | 兩個&。表示「邏輯與」。此符號兩端的條件必須全為真,整個條件測試才為真;只要有一個不為真,整個條件測試為假。 |
II | 兩個豎線。表示「邏輯或」。此符號兩端的條件只要有一個為真,整個條件測試就為真;只有兩個都為假,整個條件測試才為假。 |
來看一個例子:
#!/bin/bash
if [ $# -ge 1 ] && [ $1 = 'love' ]
then
echo "Great !"
echo "You know the password"
else
echo "You do not know the password"
fi複製程式碼
「 Great ! You know the password 」是英語「好極了!你知道密碼」的意思。
「 You do not know the password 」是英語「你不知道密碼」的意思。
上面的測試檢驗了兩個條件:
- 引數是否至少有 1 個 ( $# 大於或等於 1 )
- 第一個引數是否等於 love( $1 是否等於 love )
在做多個條件的判斷時,是按照從左到右的順序判斷的,如果前一個條件已經足以決定整個條件測試的真或假,那麼後面的條件就不會被判斷。
例如 [ 2 -ge 1 ] || [ 3 -gt 2 ] 中,2 是大於等於 1 的,因此,「 2 -ge 1 」已經為真,整個條件語句肯定為真,「 3 -gt 2 」就不需要被判斷了。
而 [ 2 -ge 4 ] && [ 5 -gt 2 ] 中,2 是小於 4 的,因此,「 2 -ge 4 」已經為假,整個條件語句肯定為假,「 5 -gt 2 」就不需要被判斷了。
反轉測試
我們可以用「否定」來反轉測試條件,要用到感嘆號( ! )。
來看一個例子:
#!/bin/bash
read -p 'Enter a file : ' file
if [ ! -e $file ]
then
echo "$file does not exist"
else
echo "$file exists"
fi複製程式碼
條件測試中我們寫了 「 ! -e $file 」,表示「如果檔案 file 不存在」。
exist 是英語「存在」的意思。
執行:
4. case : 測試多個條件
之前,我們寫過一個例子,用來演示多個條件測試的情況:
#!/bin/bash
if [ $1 = "Matthew" ]
then
echo "Hello Matthew !"
elif [ $1 = "Mark" ]
then
echo "Hello Mark !"
elif [ $1 = "Luke" ]
then
echo "Hello Luke !"
elif [ $1 = "John" ]
then
echo "Hello John !"
else
echo "Sorry, I do not know you."
fi複製程式碼
這個程式當然沒有錯,但是它只對同一個變數做測試(我們輸入的引數 1),卻用了這麼多 elif... then... 未免略顯繁瑣,也不是很好理解。
像這樣的情況,我們可以用 case 語句來實現。
case 是英語「情況」的意思。
我們上面的程式可以改寫成這樣:
#!/bin/bash
case $1 in
"Matthew")
echo "Hello Matthew !"
;;
"Mark")
echo "Hello Mark !"
;;
"Luke")
echo "Hello Luke !"
;;
"John")
echo "Hello John !"
;;
*)
echo "Sorry, I do not know you."
;;
esac複製程式碼
執行之後與之前的程式效果一樣。
來分析一下上面的程式。因為有很多新的內容:
case $1 in :$1 表示我們要測試的變數是輸入的第一個引數。in 是英語「在...之中」的意思。
"Matthew") :測試其中一個 case,也就是 $1 是否等於 "Matthew"。當然,我們也可以用星號來做萬用字元來匹配多個字元,例如 "M*") 可以匹配所有以 M 開頭的字串。
;; :類似於主流程式語言中的 「 break; 」,表示結束 case 的讀取,程式跳轉到 esac 後面執行。
*) :相當於 if 條件語句的 else,表示「否則」,就是「假如不等於上面任何一種情況」。
esac :是 case 的反寫,表示 case 語句的結束。
其實 case 語句就相當於主流程式語言中的 switch 語句。
我們也可以在case 語句的匹配項中做「或」的匹配,但是不是用兩個豎線(邏輯或)了,而是用一個豎線。
來看一個例子:
#!/bin/bash
case $1 in
"dog" | "cat" | "pig")
echo "It is a mammal"
;;
"pigeon" | "swallow")
echo "It is a bird"
;;
*)
echo "I do not know what it is"
;;
esac複製程式碼
「 It is a mammal 」是英語「這是一隻哺乳動物」的意思。
「 It is a bird 」是英語「這是一隻鳥」的意思。
「 I do not know what it is 」是英語「我不知道這是什麼」的意思。
執行:
5. 總結
我們可以用下面的語法來做條件測試:「 if, then, [ [ elif, then, fi ] else, ] fi 」。
我們可以測試字串,也可以測試數字,也可以測試檔案。例如檔案存在嗎?檔案是否可執行?等等。
如果需要,我們可以綜合好幾種測試,用 && (邏輯與),|| (邏輯非)符號。
感嘆號( ! )表示條件「否」,用於反轉條件測試。
當我們對同一個變數做好多測試時,一般用 case 語句比 if 語句更直觀。
6. 第五部分第五課預告
今天的課就到這裡,一起加油吧!
下一課我們學習:Linux探索之旅 | 第五部分第五課:迴圈往復,Shell開路
微信公眾號「程式設計師聯盟」ProgrammerLeague
我是謝恩銘,在巴黎奮鬥的軟體工程師。
我的簡介
我的經歷
熱愛生活,喜歡游泳,略懂烹飪。
人生格言:“向著標杆直跑”