結(jié)構(gòu)化命令 之 if-then九杂; if-then-else語句

本篇內(nèi)容均摘自《Linux命令行與shell腳本編程大全》尼酿,個(gè)人認(rèn)為需要重點(diǎn)學(xué)習(xí)的章節(jié)。【免費(fèi)】Linux命令行與Shell腳本編程大全 第3版 PDF全本 21MB 百度網(wǎng)盤下載 - 今夕是何夕 - 博客園

許多程序要求對(duì)shell腳本中的命令施加一些邏輯流程控制涎永。有一類命令會(huì)根據(jù)條件使腳本跳過某些命令鹿响。這樣的命令通常稱為結(jié)構(gòu)化命令( structured command)。結(jié)構(gòu)化命令允許你改變程序執(zhí)行的順序妈倔。
使用 if-then 語句
最基本的結(jié)構(gòu)化命令就是if-then語句绸贡。 if-then語句有如下格式:
if command
then
commands
fi
如果該命令的退出狀態(tài)碼(參見第11章)是0(該命令成功運(yùn)行)听怕,位于then部分的命令就會(huì)被執(zhí)行。如果該命令的退出狀態(tài)碼是其他值闽烙, then部分的命令就不會(huì)被執(zhí)行声搁, bash shell會(huì)繼續(xù)執(zhí)行腳本中的下一個(gè)命令疏旨。 fi語句用來表示if-then語句到此結(jié)束。這里有個(gè)簡單的例子可解釋這個(gè)概念莫换。

$ cat test1.sh
#!/bin/bash
# testing the if statement
if pwd
then
echo "It worked"
fi

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

$ ./test1.sh
/home/Christine
It worked

shell執(zhí)行了if行中的pwd命令丛版。由于退出狀態(tài)碼是0,它就又執(zhí)行了then部分的echo語句胖替。下面是另外一個(gè)例子独令。

$ cat test2.sh
#!/bin/bash
# testing a bad command
if IamNotaCommand
then
echo "It worked"
fi
echo "We are outside the if statement"
$ ./test2.sh
./test2.sh: line 3: IamNotaCommand: command not found
We are outside the if statement

在這個(gè)例子中好芭,我們在if語句行故意放了一個(gè)不能工作的命令舍败。由于這是個(gè)錯(cuò)誤的命令,所以它會(huì)產(chǎn)生一個(gè)非零的退出狀態(tài)碼裙戏,且bash shell會(huì)跳過then部分的echo語句弛说。還要注意,運(yùn)行if語句中的那個(gè)錯(cuò)誤命令所生成的錯(cuò)誤消息依然會(huì)顯示在腳本的輸出中信柿。
[說明] 你可能在有些腳本中看到過if-then語句的另一種形式:
if command; then
commands
fi
通過把分號(hào)放在待求值的命令尾部渔嚷,就可以將then語句放在同一行上了稠曼,這樣看起來更像其他編程語言中的if-then語句。在then部分漠吻,你可以使用不止一條命令途乃。可以像在腳本中的其他地方一樣在這里列出多條命令烫饼。 bash shell會(huì)將這些命令當(dāng)成一個(gè)塊试读,如果if語句行的命令的退出狀態(tài)值為0钩骇,所有的命令都會(huì)被執(zhí)行;如果if語句行的命令的退出狀態(tài)不為0韩容,所有的命令都會(huì)被跳過唐瀑。

$ cat test3.sh
#!/bin/bash
# testing multiple commands in the then section
#
testuser=Christine
#
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文件毅弧。

$ ./test3.sh
Christine:x:501:501:Christine B:/home/Christine:/bin/bash
This is my first command
This is my second command
I can even put in other commands besides echo:
/home/Christine/.bash_history /home/Christine/.bash_profile
/home/Christine/.bash_logout /home/Christine/.bashrc

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

$ cat test3.sh
#!/bin/bash
# testing multiple commands in the then section
#
testuser=NoSuchUser
#
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)碼, bash shell會(huì)繼續(xù)執(zhí)行腳本中的下一條命令枣耀。在這種情況下霉晕,如果能夠執(zhí)行另一組命令就好了。這正是if-then-else語句的作用捞奕。
if-then-else語句在語句中提供了另外一組命令牺堰。
if command
then
commands
else
commands
fi
當(dāng)if語句中的命令返回退出狀態(tài)碼0時(shí), then部分中的命令會(huì)被執(zhí)行颅围,這跟普通的if-then語句一樣伟葫。當(dāng)if語句中的命令返回非零退出狀態(tài)碼時(shí), bash shell會(huì)執(zhí)行else部分中的命令≡捍伲現(xiàn)在可以復(fù)制并修改測試腳本來加入else部分筏养。

$ cp test3.sh test4.sh
$
$ nano test4.sh
$
$ cat test4.sh
#!/bin/bash
# testing the else section
#
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部分可以包含多條命令。 fi語句說明else部分結(jié)束了弄抬。

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

$ ls -d /home/NoSuchUser/
/home/NoSuchUser/
$
$ cat test5.sh
#!/bin/bash
# Testing nested ifs
#
testuser=NoSuchUser
#
if grep $testuser /etc/passwd
then
echo "The user $testuser exists on this system."
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è)要測試的命令坏瞄,這類似于原始的if語句行桂对。如果elif后命令的退出狀態(tài)碼是0,則bash會(huì)執(zhí)行第二個(gè)then語句部分的命令鸠匀。使用這種嵌套方法蕉斜,代碼更清晰,邏輯更易懂缀棍。

$ cat test5.sh
#!/bin/bash
# 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/bash
# 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
[sudo] password for Christine:
$
$ ./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è)測試腳本執(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í)行。記住淹禾, bash shell會(huì)依次執(zhí)行if語句馁菜,只有第一個(gè)返回退出狀態(tài)碼0的語句中的then部分會(huì)被執(zhí)行。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末铃岔,一起剝皮案震驚了整個(gè)濱河市汪疮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌毁习,老刑警劉巖智嚷,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異纺且,居然都是意外死亡盏道,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門载碌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來猜嘱,“玉大人衅枫,你說我怎么就攤上這事±柿妫” “怎么了弦撩?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長论皆。 經(jīng)常有香客問我益楼,道長,這世上最難降的妖魔是什么点晴? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任感凤,我火速辦了婚禮,結(jié)果婚禮上觉鼻,老公的妹妹穿的比我還像新娘俊扭。我一直安慰自己,他們只是感情好坠陈,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著捐康,像睡著了一般仇矾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上解总,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天贮匕,我揣著相機(jī)與錄音,去河邊找鬼花枫。 笑死刻盐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的劳翰。 我是一名探鬼主播敦锌,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼佳簸!你這毒婦竟也來了乙墙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤生均,失蹤者是張志新(化名)和其女友劉穎听想,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體马胧,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡汉买,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了佩脊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蛙粘。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡垫卤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出组题,到底是詐尸還是另有隱情葫男,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布崔列,位于F島的核電站梢褐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏赵讯。R本人自食惡果不足惜盈咳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望边翼。 院中可真熱鬧鱼响,春花似錦、人聲如沸组底。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽债鸡。三九已至江滨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間厌均,已是汗流浹背唬滑。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留棺弊,地道東北人晶密。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像模她,于是被迫代替她去往敵國和親稻艰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

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