分支迴圈是程式語言重要結構,它使得計算機源源不斷地給搬磚。Shell 中也有對應語法支援。
在分支迴圈結構中,判斷條件十分重要,在 Shell 中可以用test函式來判斷條件。
1 test函式
test在 Shell 用於測試判斷,如其名字所示,它可以進行一些測試,如:
- 兩個字串是否相等
- 給定路徑是否存在
- 路徑是否有各種權限
- …
語法如下:
test condition
test $a -eq 5
判斷為邏輯真,返回0,判斷值為假返回值1。返回值不能用e=$(test $a -eq 5)來獲取,這樣運算後e是空。而要用$?的方式來獲取。$?用於獲取上一條命令的返回值。
test 1 -eq 2
echo $? # output 1, which means false
test 1 -eq 1
echo $? # output 0, which means true
test的返回值可以作為條件判斷(如if else)的條件:
if test "${a}" -eq 5; then echo $a; fi
test命令也可以用單中括號([])來代替,只是使用單中括號時候,需要注意在中括號和條件之間必須有空格( )。
if [ -e ex ]; then echo "exist ex"; else echo "not exist ex"; fi
if test -e ex; then echo "exist ex"; else echo "not exist ex"; fi
1.1 路徑判斷
Linux 中檔案不一定有副檔名,檔案和資料夾的名字沒有區別。
| 函式 | 意義 |
|---|---|
-e | 路徑存在(檔案或資料夾)則返回 true,否則 false,e 是 exist 的意思 |
-d | 路徑存在且是資料夾則返回 true,否則 false,d 是 directory 的意思 |
-f | 路徑存在且是檔案則返回 true,否則 false,f 是 file 的意思 |
-n | 路徑存在且大小不為零則返回 true,否則 false,n 是 nonzero 的意思 |
-z | 路徑存在且大小為零則返回 true,否則 false,z 是 zero 的意思 |
-L/-h | 路徑存在且是連結則返回 true,否則 false,L 是 link 的意思 |
-r | 路徑存在且有 read 權限則返回 true,否則 false,r 是 read 的意思 |
-w | 路徑存在且有 write 權限則返回 true,否則 false,w 是 write 的意思 |
-x | 路徑存在且有 execute 權限則返回 true,否則 false,x 是 execute 的意思 |
if [ -e $a ]; then echo "exist $a"; fi
if [ -d $a ]; then echo "exist directory $a"; fi
if [ -f $a ]; then echo "exist file $a"; fi
if [ -n $a ]; then echo "$a is not None"; fi
if [ -z $a ]; then echo "$a is None"; fi
if [ -L $a ]; then echo "exist link $a"; fi
if [ -r $a ]; then echo "$a has read access"; fi
if [ -w $a ]; then echo "$a has write access"; fi
if [ -x $a ]; then echo "$a has execute access"; fi
1.2 檔案比較
test命令也可以用於兩個檔案的比較。
| 函式 | 意義 |
|---|---|
patha -nt pathb | patha修改時間比pathb新則返回 true,否則 false,nt 是 newer than 的意思 |
patha -ot pathb | patha修改時間比pathb舊則返回 true,否則 false,ot 是 older than 的意思 |
patha -ef pathb | patha和pathb有相同 device 和 innode number 則返回 true,否則 false |
if test $a -nt $b; then echo "$a is newer than $b"; fi
if test $a -ot $b; then echo "$a is older than $b"; fi
1.3 整數比較
下面針對的是整數判斷,如果不是整數,則會報錯。
| 函式 | 意義| |
|---|---|
-eq | 兩整數相等則返回 true,否則 false,eq 是 equal 的意思,若輸入不是倆整數,則報錯 |
-gt | 兩整數前者大於後者則返回 true,否則 false,gt 是 greater than 的意思,若輸入不是倆整數,則報錯 |
\> | 含義同-gt,為了和重定向符號區分,則需要轉義 |
-lt | lt 是 less than 的意思 |
\< | 同-lt |
-ge | ge 是 greater eqaul 的意思,注意沒有\>=這種寫法 |
-le | ge 是 less eqaul 的意思,注意沒有\<=這種寫法 |
if test $a -eq $b; then echo "$a eqals $b"; fi
1.4 字串不相等判斷
=和!=針對字串。字串完全相同則是相等,有一點不同則是不等。
| 函式 | 意義| |
|---|---|
= | 兩字串相同則返回 true,否則 false,判斷字串的等號左右都是有空格的 |
!= | 兩字串不同則返回 true,否則 false,gt 是 greater than 的意思,若輸入不是倆整數,則報錯 |
if test $a = $b; then echo "$a eqals $b"; fi
2 分支結構
就是條件判斷,在不同條件下執行不同的操作。常見有if else,do while,case esac這幾種。
2.1 if else結構
if condition; then xxx; fi
if condition; then xxx; else yyy; fi
if condition_1; then xxx; elif condition_2;then yyy; else zzz; fi
2.2 case esac結構
如果有多個選項,可以用一堆if elif else,也可以用case esac的結構。
這個和 c 語言中的switch case是一樣的。不過這個esac是個什麼鬼?看看if結尾的fi就能大霧了。🐶
語法如下:
case $x in
1) echo "select 1";;
2) echo "select 2";;
3) echo "select 3";;
*) echo "select nothing";;
esac
最後的星號*表示啥也沒有選到,預設值。最後兩個分號(;;)是跳出當前case esac的意思,和其它語言中的break很相似。不過 shell script 本身就是有break和continue關鍵字的,和 c 語言中的關鍵字是一樣的。
3 迴圈結構
常見的迴圈結構有for、while、until三種:
for x in xxxx;
do
xyz_operation
done
while condition:
do
xyz
done
until condition
do
xyz
done
如果要一直執行,則可以使用while true死迴圈一直執行。
在
continue是跳出當前迴圈,繼續下一次迴圈的意思。
break是跳出整個迴圈。
當然continue和break都可以在後面接一個數字n,表示是跳出當前第n層迴圈的意思。
4 條件邏輯運算
4.1 分支中的條件運算
Shell 中表示式的結果可以進行與或非邏輯連線:
| 函式 | 含義 |
|---|---|
-a/&& | 邏輯與 |
-o/|| | 邏輯或 |
! | 邏輯非 |
if [ x -eq 5 ] && [ y -eq 6]; then echo "help"; fi
if test x -eq 5 && test y -eq 6; then echo "help"; fi
if ![ x -eq 5 ]; then echo "help"; fi
4.2 條件級連運算
對於命令也可以進行邏輯運算。
command_1 && command_2
這裡還有一個好處,如果command_1已經返回邏輯假,則command_2就可以不執行了。
if [ ! -d ${path1} ]; then
mdkir -p ${path1}
fi
上面的寫法就可以簡寫:
[ ! -d ${path1} ] && mkdir -p ${path1}
同樣,對於或運算而言,如果第一個條件滿足,後面的就不會執行了。這樣的寫法可以使程式碼更加簡潔。
總結
本文介先紹了 Shell 中的test命令,用於判斷各種情況,然後介紹了 Shell 中的分支迴圈語法,以及條件級連運算。