前言
只要講到程序的話,那么條件判斷式,即是
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)。因此elif
的then
代碼塊中的語句得以執(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í)行。
參考資料
- 結(jié)構(gòu)化命令之 if-then;if-then-else語句
- 《鳥哥的Linux私房菜》
- 《Linux命令行與shell腳本編程大全》