1. 程式人生 > 其它 >SHELL-流程控制

SHELL-流程控制

目錄

SHELL指令碼-流程控制

1 if-then語句-判斷

1.1 基本結構

if command;then
  commands
fi

該結構的if語句可以用於判斷if後的command是否執行成功,當該command執行成功(狀態返回碼為0),則執行then後的語句,否則退出。

if command;then
  commands
else
  commands
fi

該結構的if語句與上一結構功能類似,只是當command執行不成功的時候,執行else後的語句。

1.2 巢狀if

if command;then
  commands
elif command;then
  commands
else 
  commands
fi

這種巢狀的if語句,使用elif用於測試另外的命令,如果if後的command退出狀態碼為非0,則會測試elif後的命令,如果elif後的命令退出狀態碼為0則會執行,elif後的then語句,否則執行else語句。所以緊跟在elif語句的else語句,是屬於elif的程式碼塊,而不是if-then的程式碼塊。

通過將多個elif語句聯合起來,可以形成一個大規模的if-then-elif的巢狀組,從而實現類似於case語句的功能。

if command;then
  commands
elif command;then
  commands
elif command;then
  commands
elif command;then
  commands
fi

1.3 if的條件判斷

與其他高階語言相同,if語句不僅可以根據命令的執行狀態進行選擇判斷,也可以通過判斷條件是否成立執行命令。

儘管if語句中的條件判斷可以通過test命令實現,但最常使用的條件判斷方法是使用方括號。

if [ condition ];then
  commands
else
  commands
fi

通過方括號執行條件判斷需要注意的是,在條件判斷語句和方括號左右兩邊均有空格隔開。

1.3.1 數值比較

假定變數 a 為 5,變數 b 為 10:

運算子 說明 舉例
-eq 檢測兩個數是否相等,相等返回 true。 [ $a -eq $b ] 返回 false。
-ne 檢測兩個數是否不相等,不相等返回 true。 [ $a -ne $b ] 返回 true。
-gt 檢測左邊的數是否大於右邊的,如果是,則返回 true。 [ $a -gt $b ] 返回 false。
-lt 檢測左邊的數是否小於右邊的,如果是,則返回 true。 [ $a -lt $b ] 返回 true。
-ge 檢測左邊的數是否大於等於右邊的,如果是,則返回 true。 [ $a -ge $b ] 返回 false。
-le 檢測左邊的數是否小於等於右邊的,如果是,則返回 true。 [ $a -le $b ] 返回 true。

1.3.2 字串比較

下表列出了常用的字串運算子,假定變數 a 為 "abc",變數 b 為 "efg":

運算子 說明 舉例
= 檢測兩個字串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
!= 檢測兩個字串是否不相等,不相等返回 true。 [ $a != $b ] 返回 true。
-z 檢測字串長度是否為0,為0返回 true。 [ -z $a ] 返回 false。
-n 檢測字串長度是否不為 0,不為 0 返回 true。 [ -n "$a" ] 返回 true。
$ 檢測字串是否為空,不為空返回 true。 [ $a ] 返回 true。

1.3.3 檔案比較

操作符 說明 舉例
-b file 檢測檔案是否是塊裝置檔案,如果是,則返回 true。 [ -b $file ] 返回 false。
-c file 檢測檔案是否是字元裝置檔案,如果是,則返回 true。 [ -c $file ] 返回 false。
-d file 檢測檔案是否是目錄,如果是,則返回 true。 [ -d $file ] 返回 false。
-f file 檢測檔案是否是普通檔案(既不是目錄,也不是裝置檔案),如果是,則返回 true。 [ -f $file ] 返回 true。
-g file 檢測檔案是否設定了 SGID 位,如果是,則返回 true。 [ -g $file ] 返回 false。
-k file 檢測檔案是否設定了粘著位(Sticky Bit),如果是,則返回 true。 [ -k $file ] 返回 false。
-p file 檢測檔案是否是有名管道,如果是,則返回 true。 [ -p $file ] 返回 false。
-u file 檢測檔案是否設定了 SUID 位,如果是,則返回 true。 [ -u $file ] 返回 false。
-r file 檢測檔案是否可讀,如果是,則返回 true。 [ -r $file ] 返回 true。
-w file 檢測檔案是否可寫,如果是,則返回 true。 [ -w $file ] 返回 true。
-x file 檢測檔案是否可執行,如果是,則返回 true。 [ -x $file ] 返回 true。
-s file 檢測檔案是否為空(檔案大小是否大於0),不為空返回 true。 [ -s $file ] 返回 true。
-e file 檢測檔案(包括目錄)是否存在,如果是,則返回 true。 [ -e $file ] 返回 true。

其他檢查符:

  • -S: 判斷某檔案是否 socket。
  • -L: 檢測檔案是否存在並且是一個符號連結。

1.4 if-then的高階特性

  • 通過使用雙方括號不僅可以使用標準的字串比較,也可以通過正則表示式匹配字元。
  • 通過使用雙括號可以使用任意的書序賦值或比較表示式,雙括號用到的其他運算子如下表
符號 描述
val++ 後增
val-- 後減
++val 先增
--val 先減
邏輯求反
~ 位求反
** 冪運算
<< 左位移
>> 右位移
& 位布林和
| 位布林或
&& 邏輯和
|| 邏輯或

1.5 case 語句

case var in
pattern1)
  commands1
  ;;
pattern2)
  commands2
  ;;
*)
  commands3
  ;;
esac

case語句用於匹配同一變數的不同值,避免了使用if-then-elif的迴圈巢狀導致的邏輯混亂。語法結構更加清晰。

2 for while 迴圈語句

2.1 for語句基本格式

for var in list;do 
 commands 
done

在list引數中,你需要提供迭代中要用到的一系列值。可以通過幾種不同的方法指定列表 中的值。

在每次迭代中,變數var會包含列表中的當前值。第一次迭代會使用列表中的第一個值,第 二次迭代使用第二個值,以此類推,直到列表中的所有值都過一遍。

在do和done語句之間輸入的命令可以是一條或多條標準的bash shell命令。在這些命令中, $var變數包含著這次迭代對應的當前列表項中的值。

list的值可以是數字,也可以是字串。列表的值可以是由自己定義而來的,也可以是命令執行後的結果。常見的幾種迭代定義方法:

#var值由192.168.1.2-192.168.1.150中迴圈迭代
for var in 192.168.1.{2..150}    
#var值迭代資料夾/etc/下的所有檔案或目錄(萬用字元方法)
for var in /etc/*
#var值迭代資料夾/etc/下的所有檔案或目錄
for var in $(ls /etc)
#var值迭代1-6
for var in {1..6}

2.2 更改欄位分隔符

for迭代字串的中各個字串的方法是由一個特殊的環境變數IFS定義的,預設的情況下bash shell會將下列字元當做欄位分隔符:

  • 空格
  • 製表符
  • 換行符

可以在shell指令碼中定義IFS的值變更分割符號如IFS=:

在處理程式碼量較大的指令碼時,可能在一個地方需要修改IFS的值,然後忽略這次修改,在
指令碼的其他地方繼續沿用IFS的預設值。一個可參考的安全實踐是在改變IFS之前儲存原
來的IFS值,之後再恢復它。
這種技術可以這樣實現:
 IFS.OLD=$IFS 
 IFS=$'\n' 
 <在程式碼中使用新的IFS值> 
 IFS=$IFS.OLD 
這就保證了在指令碼的後續操作中使用的是IFS的預設值

2.3 C語言風格的for迴圈

在shell指令碼中可以通過雙括號實現C語言風格的for迴圈,如:for (( i=1; i <= 10; i++ ))

for迴圈通過定義好的變數(本例中是變數i)來迭代執行這些命令。在每次迭代中,$i變 量包含了for迴圈中賦予的值。在每次迭代後,迴圈的迭代過程會作用在變數上,在本例中,變 量增一。

也可以同時迭代兩個變數如:for (( a=1, b=10; a <= 10; a++, b-- ))

2.4 while迴圈

while迴圈可以視作某種if-then與for迴圈的混雜體。對while迴圈設定一個跳出迴圈條件,如果不符合條件將一直迴圈下去。設定條件的方式和if-then語句完全一樣。需要注意的是當設定條件的時候,需要明確自己是需要一個死迴圈還是有限迴圈,並根據設計的目的,新增變數迭代方式。

while迴圈的基本結果如:

while test command ;do 
 other commands 
done 

通過while ture可以實現程式碼的死迴圈,當然即使設定死迴圈也需要通過break設定跳出迴圈的條件。

2.5 until迴圈

until命令和while命令工作的方式完全相反。until命令要求你指定一個通常返回非零退 出狀態碼的測試命令。只有測試命令的退出狀態碼不為0,bash shell才會執行迴圈中列出的命令。 一旦測試命令返回了退出狀態碼0,迴圈就結束了。

until的基本格式如:

untile test command;do
  other commands
done

2.6 控制迴圈

你可能會想,一旦啟動了迴圈,就必須苦等到迴圈完成所有的迭代。並不是這樣的。有兩個 命令能幫我們控制迴圈內部的情況:

  • break
  • continue

break命令可以直接跳出迴圈,不執行剩餘的迭代任務。break預設只跳出一層迴圈,如果有巢狀迴圈的存在,需要跳出多層迴圈,可以通過break n。n為1,表明跳出的是當前的迴圈(這也是預設設定)。如果你將 n設為2,break命令就會停止下一級的外部迴圈。

continue命令可以提前中止某次迴圈中的命令,但並不會完全終止整個迴圈。在當前迴圈中,剩餘的命令將不會被執行,而直接進入下一次的迴圈。