if條件測試語句可以讓腳本根據實際情況自動執行相應的命令。從技術角度來講,if語句分為單分支結構、雙分支結構、多分支結構;其復雜度隨着靈活度一起逐級上升。
if條件語句的單分支結構由if、then、fi關鍵詞組成,而且只在條件成立后才執行預設的命令,相當於口語的“如果……那么……”。單分支的if語句屬於最簡單的一種條件判斷結構,語法格式如圖4-17所示。

圖4-17 單分支的if語句
下面使用單分支的if條件語句來判斷/media/cdrom文件是否存在,若存在就結束條件判斷和整個Shell腳本,反之則去創建這個目錄:
[root@linuxprobe ~]# vim mkcdrom.sh #!/bin/bash DIR="/media/cdrom" if [ ! -e $DIR ] then mkdir -p $DIR fi
由於第5章才講解用戶身份與權限,因此這里繼續用“bash 腳本名稱”的方式來執行腳本。在正常情況下,順利執行完腳本文件后沒有任何輸出信息,但是可以使用ls命令驗證/media/cdrom目錄是否已經成功創建:
[root@linuxprobe ~]# bash mkcdrom.sh [root@linuxprobe ~]# ls -d /media/cdrom /media/cdrom
if條件語句的雙分支結構由if、then、else、fi關鍵詞組成,它進行一次條件匹配判斷,如果與條件匹配,則去執行相應的預設命令;反之則去執行不匹配時的預設命令,相當於口語的“如果……那么……或者……那么……”。if條件語句的雙分支結構也是一種很簡單的判斷結構,語法格式如圖4-18所示。

圖4-18 雙分支的if條件語句
下面使用雙分支的if條件語句來驗證某台主機是否在線,然后根據返回值的結果,要么顯示主機在線信息,要么顯示主機不在線信息。這里的腳本主要使用ping命令來測試與對方主機的網絡聯通性,而Linux系統中的ping命令不像Windows一樣嘗試4次就結束,因此為了避免用戶等待時間過長,需要通過-c參數來規定嘗試的次數,並使用-i參數定義每個數據包的發送間隔,以及使用-W參數定義等待超時時間。
[root@linuxprobe ~]# vim chkhost.sh #!/bin/bash ping -c 3 -i 0.2 -W 3 $1 &> /dev/null if [ $? -eq 0 ] then echo "Host $1 is On-line." else echo "Host $1 is Off-line." fi
我們在4.2.3小節中用過$?變量,作用是顯示上一次命令的執行返回值。若前面的那條語句成功執行,則$?變量會顯示數字0,反之則顯示一個非零的數字(可能為1,也可能為2,取決於系統版本)。因此可以使用整數比較運算符來判斷$?變量是否為0,從而獲知那條語句的最終判斷情況。這里的服務器IP地址為192.168.10.10,我們來驗證一下腳本的效果:
[root@linuxprobe ~]# bash chkhost.sh 192.168.10.10 Host 192.168.10.10 is On-line. [root@linuxprobe ~]# bash chkhost.sh 192.168.10.20 Host 192.168.10.20 is Off-line.
if條件語句的多分支結構由if、then、else、elif、fi關鍵詞組成,它進行多次條件匹配判斷,這多次判斷中的任何一項在匹配成功后都會執行相應的預設命令,相當於口語的“如果……那么……如果……那么……”。if條件語句的多分支結構是工作中最常使用的一種條件判斷結構,盡管相對復雜但是更加靈活,語法格式如圖4-19所示。 
圖 4-19 多分支的if條件語句
下面使用多分支的if條件語句來判斷用戶輸入的分數在哪個成績區間內,然后輸出如Excellent、Pass、Fail等提示信息。在Linux系統中,read是用來讀取用戶輸入信息的命令,能夠把接收到的用戶輸入信息賦值給后面的指定變量,-p參數用於向用戶顯示一定的提示信息。在下面的腳本示例中,只有當用戶輸入的分數大於等於85分且小於等於100分,才輸出Excellent字樣;若分數不滿足該條件(即匹配不成功),則繼續判斷分數是否大於等於70分且小於等於84分,如果是,則輸出Pass字樣;若兩次都落空(即兩次的匹配操作都失敗了),則輸出Fail字樣:
[root@linuxprobe ~]# vim chkscore.sh #!/bin/bash read -p "Enter your score(0-100):" GRADE if [ $GRADE -ge 85 ] && [ $GRADE -le 100 ] ; then echo "$GRADE is Excellent" elif [ $GRADE -ge 70 ] && [ $GRADE -le 84 ] ; then echo "$GRADE is Pass" else echo "$GRADE is Fail" fi [root@linuxprobe ~]# bash chkscore.sh Enter your score(0-100):88 88 is Excellent [root@linuxprobe ~]# bash chkscore.sh Enter your score(0-100):80 80 is Pass
下面執行該腳本。當用戶輸入的分數分別為30和200時,其結果如下:
[root@linuxprobe ~]# bash chkscore.sh Enter your score(0-100):30 30 is Fail [root@linuxprobe ~]# bash chkscore.sh Enter your score(0-100):200 200 is Fail
為什么輸入的分數為200時,依然顯示Fail呢?原因很簡單—沒有成功匹配腳本中的兩個條件判斷語句,因此自動執行了最終的兜底策略。可見,這個腳本還不是很完美,建議讀者自行完善這個腳本,使得用戶在輸入大於100或小於0的分數時,給予Error報錯字樣的提示。
如果在 if中 還 想 加 入 更多的 條件 ,就 只 需要 添加
elif [ $GRADE -ge 70 ] && [ $GRADE -le 84 ] ; then echo "$GRADE is Pass"
#!/bin/bash
read -p "Enter your score(0-100):" GRADE
if [ $GRADE -ge 85 ] && [ $GRADE -le 100 ] ; then
echo "$GRADE is Excellent"
elif [ $GRADE -ge 70 ] && [ $GRADE -le 84 ] ; then
echo "$GRADE is henhao"
elif [ $GRADE -ge 60 ] && [ $GRADE -le 69 ] ; then
echo "$GRADE is Pass"
else
echo "$GRADE is Fail"
fi
4.3.2 for條件循環語句
for循環語句允許腳本一次性讀取多個信息,然后逐一對信息進行操作處理,當要處理的數據有范圍時,使用for循環語句再適合不過了。for循環語句的語法格式如圖4-20所示。

圖4-20 for循環語句的語法格式
下面使用for循環語句從列表文件中讀取多個用戶名,然后為其逐一創建用戶賬戶並設置密碼。首先創建用戶名稱的列表文件users.txt,每個用戶名稱單獨一行。讀者可以自行決定具體的用戶名稱和個數:
[root@linuxprobe ~]# vim users.txt andy barry carl duke eric george
接下來編寫Shell腳本Example.sh。在腳本中使用read命令讀取用戶輸入的密碼值,然后賦值給PASSWD變量,並通過-p參數向用戶顯示一段提示信息,告訴用戶正在輸入的內容即將作為賬戶密碼。在執行該腳本后,會自動使用從列表文件users.txt中獲取到所有的用戶名稱,然后逐一使用“id 用戶名”命令查看用戶的信息,並使用$?判斷這條命令是否執行成功,也就是判斷該用戶是否已經存在。
需要多說一句,/dev/null是一個被稱作Linux黑洞的文件,把輸出信息重定向到這個文件等同於刪除數據(類似於沒有回收功能的垃圾箱),可以讓用戶的屏幕窗口保持簡潔。
[root@linuxprobe ~]# vim Example.sh #!/bin/bash read -p "Enter The Users Password : " PASSWD for UNAME in `cat users.txt` do id $UNAME &> /dev/null if [ $? -eq 0 ] then echo "Already exists" else useradd $UNAME &> /dev/null echo "$PASSWD" | passwd --stdin $UNAME &> /dev/null if [ $? -eq 0 ] then echo "$UNAME , Create success" else echo "$UNAME , Create failure" fi fi done
執行批量創建用戶的Shell腳本Example.sh,在輸入為賬戶設定的密碼后將由腳本自動檢查並創建這些賬戶。由於已經將多余的信息通過輸出重定向符轉移到了/dev/null黑洞文件中,因此在正常情況下屏幕窗口除了“用戶賬戶創建成功”(Create success)的提示后不會有其他內容。
