和即將用到Shell的人們談談Shell 流程控制


Shell 流程控制

if..else語句

單分支

if 條件;then

條件為真的分支代碼

fi

雙分支

if 條件;then

條件為真的分支代碼

else

條件為假的分支代碼

fi

多分支

if 條件1;then

條件為真的分支代碼

elif 條件2;then

條件為真的分支代碼

else

條件為假的分支代碼

fi

if 語句語法格式:

if criteria

then

directive1

directive2

...

directiveN

fi

寫成一行(適用於終端命令提示符):

if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi

末尾的fi就是if倒過來拼寫,後面還會遇到類似的。

if else

if else 語法格式:

if criteria

then

directive1

directive2

...

directiveN

else

directive

fi

if else-if else

if else-if else 語法格式:

if criteria1

then

directive1

elif criteria2

directive2

else

directiveN

fi

if else語句經常與test命令結合使用,如下所示:

num1=$[2*3]

num2=$[1+5]

if test $[num1] -eq $[num2]

then

echo '兩個數字相等!'

else

echo '兩個數字不相等!'

fi

輸出結果:

兩個數字相等!

判斷條件:每一次遇到為“真”的條件,執行其分支語句,然後結束整個進程。當然if語句是可以嵌套的。

for 循環

與其他編程語言類似,Shell支持for循環。

for循環一般格式為:

for var in item1 item2 ... itemN

do

directive1

directive2

...

directiveN

done

寫成一行:

for var in item1 item2 ... itemN; do directive1; directive2… done;

當變量值在列表裡,for循環即執行一次所有命令,使用變量名獲取列表中的當前取值。命令可為任何有效的shell命令和語句。in列表可以包含替換、字符串和文件名。

in列表是可選的,如果不用它,for循環使用命令行的位置參數。

例如,順序輸出當前列表中的數字:

for loop in 1 2 3 4 5

do

echo "The value is: $loop"

done

輸出結果:

The value is: 1

The value is: 2

The value is: 3

The value is: 4

The value is: 5

順序輸出字符串中的字符:

for str in 'This is a string'

do

echo $str

done

輸出結果:

This is a string

例如,打印99乘法表 思路:使用兩層循環,內層的循環變量引用外層的循環變量。

[root@localhost bin]# vim for7_9x9.sh

for i in {1..9}

do

for j in `seq 1 $i`;do

echo -e "$i*$j=$[i*j] \\c\\t"

done

echo

done

unset i j

[root@localhost bin]# ./for7_9x9.sh

1*1=1

2*1=2 2*2=4

3*1=3 3*2=6 3*3=9

4*1=4 4*2=8 4*3=12 4*4=16

5*1=5 5*2=10 5*3=15 5*4=20 5*5=25

6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36

7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49

8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64

9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81

while 語句

while循環用於不斷執行一系列命令,也用於從輸入文件中讀取數據;命令通常為測試條件。其格式為:

while criteria

do

directive

done

以下是一個基本的while循環,測試條件是:如果int小於等於5,那麼條件返回真。int從0開始,每次循環處理時,int加1。運行上述腳本,返回數字1到5,然後終止。

#!/bin/sh

int=1

while(( $int<=5 )) do echo $int let "int++" done

運行腳本,輸出:

1

2

3

4

5

while循環可用於讀取鍵盤信息。下面的例子中,輸入信息被設置為變量FILM,按<ctrl-d>結束循環。/<ctrl-d>

echo '按下 <ctrl-d> 退出'/<ctrl-d>

echo -n '輸入你最喜歡的電影名: '

while read FILM

do

echo "是的!$FILM 是一部好電影"

done

運行腳本,輸出類似下面:

按下 <ctrl-d> 退出/<ctrl-d>

輸入你最喜歡的電影名: IYSMS在線教程

是的!IYSMS在線教程 是一部好教程

無限循環

無限循環語法格式:

while :

do

directive

done

或者

while true

do

directive

done

或者

for (( ; ; ))

例如,編寫腳本,求100以內所有正奇數之和。

[root@localhost bin]# vim while1_jishusum.sh

sum=0

i=1

while [ $i -le 100 ];do

if [ $[$i%2] -eq 1 ];then

let sum=sum+i

fi

let i++

done

echo 100以內所有正奇數之和是 $sum

unset i sum

[root@localhost bin]# ./while1_jishusum.sh

100以內所有正奇數之和是 2500

until 循環

until循環執行一系列命令直至條件為真時停止。

until循環與while循環在處理方式上剛好相反。

一般while循環優於until循環,但在某些時候—也只是極少數情況下,until循環更加有用。

until 語法格式:

until criteria

do

directive

done

條件可為任意測試條件,測試發生在循環末尾,因此循環至少執行一次—請注意這一點。

case

Shell case語句為多選擇語句。可以用case語句匹配一個值與一個模式,如果匹配成功,執行相匹配的命令。case語句格式如下:

case 值 in

模式1)

directive1

directive2

...

directiveN

;;

模式2)

directive1

directive2

...

directiveN

;;

esac

case工作方式如上所示。取值後面必須為單詞in,每一模式必須以右括號結束。取值可以為變量或常數。匹配發現取值符合某一模式後,其間所有命令開始執行直至 ;;。

取值將檢測匹配的每一個模式。一旦模式匹配,則執行完匹配模式相應命令後不再繼續其他模式。如果無一匹配模式,使用星號 * 捕獲該值,再執行後面的命令。

下面的腳本提示輸入1到4,與每一種模式進行匹配:

echo '輸入 1 到 4 之間的數字:'

echo '你輸入的數字為:'

read aNum

case $aNum in

1) echo '你選擇了 1'

;;

2) echo '你選擇了 2'

;;

3) echo '你選擇了 3'

;;

4) echo '你選擇了 4'

;;

*) echo '你沒有輸入 1 到 4 之間的數字'

;;

esac

輸入不同的內容,會有不同的結果,例如:

輸入 1 到 4 之間的數字:

你輸入的數字為:

3

你選擇了 3

跳出循環

在循環過程中,有時候需要在未達到循環結束條件時強制跳出循環,Shell使用兩個命令來實現該功能:break和continue。

break命令

break命令允許跳出所有循環(終止執行後面的所有循環)。

下面的例子中,腳本進入死循環直至用戶輸入數字大於5。要跳出這個循環,返回到shell提示符下,需要使用break命令。

#!/bin/bash

while :

do

echo -n "輸入 1 到 5 之間的數字:"

read aNum

case $aNum in

1|2|3|4|5) echo "你輸入的數字為 $aNum!"

;;

*) echo "你輸入的數字不是 1 到 5 之間的! This game is over!"

break

;;

esac

done

執行以上代碼,輸出結果為:

輸入 1 到 5 之間的數字:3

你輸入的數字為 3!

輸入 1 到 5 之間的數字:7

你輸入的數字不是 1 到 5 之間的! 遊戲結束

continue

continue命令與break命令類似,只有一點差別,它不會跳出所有循環,僅僅跳出當前循環。

對上面的例子進行修改:

#!/bin/bash

while :

do

echo -n "輸入 1 到 5 之間的數字: "

read aNum

case $aNum in

1|2|3|4|5) echo "你輸入的數字為 $aNum!"

;;

*) echo "你輸入的數字不是 1 到 5 之間的!"

continue

echo "This game is over!"

;;

esac

done

運行代碼發現,當輸入大於5的數字時,該例中的循環不會結束,語句 echo "This game is over!" 永遠不會被執行。

esac

case的語法和C family語言差別很大,它需要一個esac(就是case反過來)作為結束標記,每個case分支用右圓括號,用兩個分號表示break。

select

select 常用於菜單,常與case組合達到菜單的效果。

使用PS3,顯示用戶界面提示符,相等於read -p 的效果

$REPLY變量的select的內置變量,用來引用用戶輸入。

[root@localhost bin]# vim menufoods.sh

PS3="請選擇菜單編號:"

select menu in 米飯 炒菜 麵條 饅頭 退出

do

case $REPLY in

1|4)

echo this price is 20

;;

2|3)

echo this price is 12

;;

5)

echo byebye

exit 2

;;

*)

echo no this number !

echo $menu

esac

done

[root@localhost bin]# menufoods.sh

1) 米飯

2) 炒菜

3) 麵條

4) 饅頭

5) 退出

請選擇菜單編號:1

this price is 20

請選擇菜單編號:4

this price is 20

請選擇菜單編號:2

this price is 12

請選擇菜單編號:5

byebye