shell腳本編程之條件判斷式(一)

前言

只要講到程序的話,那么條件判斷式,即是if-then這種判別式肯定一定要學(xué)習(xí)。因?yàn)楹芏鄷r(shí)候,我們都必須依據(jù)某些數(shù)據(jù)來判斷程序該如何進(jìn)行。

if-then語句

最基本的條件判斷式是if-then語句。 if-then語句有如下格式:

if command
then
commands
fi

如果該命令的退出狀態(tài)碼是0(該命令成功運(yùn)行),位于then部分的命令就會(huì)被執(zhí)行。如果該命令的退出狀態(tài)碼是其他值, then部分的命令就不會(huì)被執(zhí)行, shell會(huì)繼續(xù)執(zhí)行腳本中的下一個(gè)命令。 fi語句用來表示if-then語句到此結(jié)束。

#!/bin/zsh
#testing the if-then statement
if pwd
then
        echo It worked
fi

這個(gè)腳本在if行采用了pwd命令(顯然會(huì)成功)。如果命令成功結(jié)束,echo語句就會(huì)顯示該文本字符串。在命令行運(yùn)行該腳本時(shí),會(huì)得到如下結(jié)果:

$ ./test1.sh
/mnt/f/linux/zsh-script/if-then
It worked

下面是另一個(gè)例子

#!/bin/zsh
#testing the if-then statement
if iloveu
then
        echo It worked
fi
echo We are outside the statement

這次我們故意執(zhí)行了一個(gè)不存在的命令iloveu,所以它會(huì)產(chǎn)生一個(gè)非零的退出狀態(tài)碼,shell會(huì)跳過then部分的echo語句。還要注意,運(yùn)行if語句中的那個(gè)錯(cuò)誤命令所生成的錯(cuò)誤消息依然會(huì)顯示在腳本的輸出中。

當(dāng)if中的命令沒有被成功執(zhí)行時(shí),shell會(huì)自動(dòng)跳過then部分的命令,直接執(zhí)行該部分后的內(nèi)容,在該例中即為語句echo We are outside the statement

另一種形式

if-then語句的另一種形式:

if command; then
commands
fi

通過把分號(hào)放在待求值的命令尾部,就可以將then語句放在同一行上了。在then部分,你可以使用不止一條命令,可以像在腳本中的其他地方一樣在這里列出多條命令。

if-then的兩種形式本質(zhì)上沒有區(qū)別,只是表現(xiàn)形式有所不同,后者在多條語句時(shí)會(huì)更加美觀。

#!/bin/zsh
#testing multiple commands in the then section
testuser=lyr
if grep $testuser /etc/passwd
then
        echo "This is my first command"
        echo "This is my second command"
        echo "I can even put in other commands besides echo: "
        ls -a /home/$testuser/.b*
fi

if語句行使用grep命令在/etc/passwd文件中查找某個(gè)用戶名當(dāng)前是否在系統(tǒng)上使用。如果有用戶使用了那個(gè)登錄名,腳本會(huì)顯示一些文本信息并列出該用戶HOME目錄的bash文件。

注意到上述腳本中我們先定義了一個(gè)用戶變量testuser,之后使用命令替換的方式引用了這個(gè)變量,此時(shí)的$testuser應(yīng)該看為lyr。

運(yùn)行結(jié)果:

$ ./test3.sh
lyr:x:1000:1000:,,,:/home/lyr:/usr/bin/zsh
This is my first command
This is my second command
I can even put in other commands besides echo:
/home/lyr/.bash_history  /home/lyr/.bash_logout  /home/lyr/.bashrc

但是,如果將testuser變量設(shè)置成一個(gè)系統(tǒng)上不存在的用戶,則什么都不會(huì)顯示。

#!/bin/zsh
#testing multiple commands in the then section
testuser=hqw    #hqw用戶名并不存在
if grep $testuser /etc/passwd
then
        echo "This is my first command"
        echo "This is my second command"
        echo "I can even put in other commands besides echo: "
        ls -a /home/$testuser/.b*
fi
$ ./test3.sh

如果在這里顯示的一些消息可說明這個(gè)用戶名在系統(tǒng)中未找到,這樣可能就會(huì)顯得更友好,可以用if-then語句的另外一個(gè)特性來做到這一點(diǎn)。

if-then-else語句

if-then語句中,不管命令是否成功執(zhí)行,你都只有一種選擇。如果命令返回一個(gè)非零退出狀態(tài)碼,shell會(huì)跳過該部分繼續(xù)執(zhí)行腳本中的下一條命令。在這種情況下,如果能夠執(zhí)行另一組命令就好了。這正是if-then-else語句的作用。

if command
then
commands
else
commands
fi

當(dāng)if語句中的命令返回退出狀態(tài)碼0時(shí), then部分中的命令會(huì)被執(zhí)行,當(dāng)if語句中的命令返回非零退出狀態(tài)碼時(shí), shell會(huì)執(zhí)行else部分中的命令。現(xiàn)在可以復(fù)制并修改測(cè)試腳本來加入else部分。

#!/bin/zsh
#testing the else function                                                                                              testuser=NoSuchUser
if grep $testuser /etc/passwd
then
        echo "The bash files for user $testuser are: "
        ls -a /home/$testuser/.b*
        echo
else
        echo "The user $testuser does not exist on this system."
        echo
fi
$ ./test4.sh
The user NoSuchUser does not exist on this system.

這樣就更友好了。跟then部分一樣, else部分可以包含多條命令。

嵌套if

要檢查/etc/passwd文件中是否存在某個(gè)用戶名以及該用戶的目錄是否尚在,可以使用嵌套的if-then語句。嵌套的if-then語句位于主if-then-else語句的else代碼塊中。

#!/bin/zsh
#testing nested ifs                                                                                                     testuser=NoSuchUser
if grep $testuser /etc/passwd
then
        echo "The bash files for user $testuser are: "                                                                  
else
        echo "The user $testuser does not exist on this system."                                                                
       if                   
              ls -d /home/$testuser                                                                                           
       then                                                                                                                            
              echo "However,$testuser has a directory"                                                                        
       fi                                                                                                              
fi
$ ./test5.sh
The user NoSuchUser does not exist on this system.
/home/NoSuchUser/
However, NoSuchUser has a directory.

這個(gè)腳本準(zhǔn)確無誤地發(fā)現(xiàn),盡管登錄名已經(jīng)從/etc/passwd中刪除了,但是該用戶的目錄仍然存在。在腳本中使用這種嵌套if-then語句的問題在于代碼不易閱讀,很難理清邏輯流程。可以使用else部分的另一種形式: elif。這樣就不用再書寫多個(gè)if-then語句了。elif使用另一個(gè)if-then語句延續(xù)else部分。

if command1
then
commands
elif command2
then
more commands
fi

elif語句行提供了另一個(gè)要測(cè)試的命令,這類似于原始的if語句行。如果elif后命令的退出狀態(tài)碼是0,則bash會(huì)執(zhí)行第二個(gè)then語句部分的命令。

$ cat test5.sh
#!/bin/zsh
# Testing nested ifs - use elif
testuser=NoSuchUser
if grep $testuser /etc/passwd
then
echo "The user $testuser exists on this system."
elif ls -d /home/$testuser
then
echo "The user $testuser does not exist on this system."
echo "However, $testuser has a directory."
fi
$ ./test5.sh
/home/NoSuchUser
The user NoSuchUser does not exist on this system.
However, NoSuchUser has a directory.

甚至可以更進(jìn)一步,讓腳本檢查擁有目錄的不存在用戶以及沒有擁有目錄的不存在用戶。這可以通過在嵌套elif中加入一個(gè)else語句來實(shí)現(xiàn)。

$ cat test5.sh
#!/bin/zsh
# Testing nested ifs - use elif & else
testuser=NoSuchUser
if grep $testuser /etc/passwd
then
echo "The user $testuser exists on this system."
elif ls -d /home/$testuser
then
echo "The user $testuser does not exist on this system."
echo "However, $testuser has a directory."
else
echo "The user $testuser does not exist on this system."
echo "And, $testuser does not have a directory."
fi
$ ./test5.sh
/home/NoSuchUser
The user NoSuchUser does not exist on this system.
However, NoSuchUser has a directory.
$ sudo rmdir /home/NoSuchUser
$ ./test5.sh
ls: cannot access /home/NoSuchUser: No such file or directory
The user NoSuchUser does not exist on this system.
And, NoSuchUser does not have a directory.

在/home/NoSuchUser目錄被刪除之前,這個(gè)測(cè)試腳本執(zhí)行的是elif語句,返回零值的退出狀態(tài)。因此elifthen代碼塊中的語句得以執(zhí)行。刪除了/home/NoSuchUser目錄之后, elif語句返回的是非零值的退出狀態(tài)。這使得elif塊中的else代碼塊得以執(zhí)行。記住,在elif語句中,緊跟其后的else語句屬于elif代碼塊。它們并不屬于之前的if-then代碼塊。
可以繼續(xù)將多個(gè)elif語句串起來,形成一個(gè)大的if-then-elif嵌套組合。

if command1
then
command set 1
elif command2
then
command set 2
elif command3
then
command set 3
elif command4
then
command set 4
fi

每塊命令都會(huì)根據(jù)命令是否會(huì)返回退出狀態(tài)碼0來執(zhí)行。記住, shell會(huì)依次執(zhí)行if語句,只有第一個(gè)返回退出狀態(tài)碼0的語句中的then部分會(huì)被執(zhí)行。

參考資料

  1. 結(jié)構(gòu)化命令之 if-then;if-then-else語句
  2. 《鳥哥的Linux私房菜》
  3. 《Linux命令行與shell腳本編程大全》
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容