一、簡介
Shell編程中迴圈命令用於特定條件下決定某些語句重複執行的控制方式,有三種常用的迴圈語句:for、while和until。while迴圈和for迴圈屬於“當型迴圈”,而until屬於“直到型迴圈”。迴圈控制符:break和continue控制流程程轉向。
二、詳解 1、for迴圈
(1)for迴圈有三種結構:一種是列表for迴圈,第二種是不帶列表for迴圈。第三種是類C風格的for迴圈。
(2)列表for迴圈
#!/bin/bashfor varible1 in {1..5}#for varible1 in 1 2 3 4 5do echo "Hello, Welcome $varible1 times "done
do和done之間的命令稱為迴圈體,執行次數和list列表中常數或字串的個數相同。for迴圈,首先將in後list列表的第一個常數或字串賦值給迴圈變數,然後執行迴圈體,以此執行list,最後執行done命令後的命令序列。 Sheel支援列表for迴圈使用略寫的計數方式,1~5的範圍用{1..5}表示(大括弧不能去掉,否則會當作一個字串處理)。 Sheel中還支援按規定的步數進行跳躍的方式實現列表for迴圈,例如計算1~100內所有的奇數之和。
#!/bin/bashsum=0for i in {1..100..2}do let "sum+=i"done echo "sum=$sum"
通過i的按步數2不斷遞增,計算sum值為2500。同樣可以使用seq命令實現按2遞增來計算1~100內的所有奇數之和,for i in $(seq 1 2 100),seq表示起始數為1,跳躍的步數為2,結束條件值為100。
for迴圈對字串進行操作,例如通過for迴圈顯示目前的目錄下所有的檔案。
#!/bin/bashfor file in $( ls )#for file in *do echo "file: $file"done
也可一使用for file in *,萬用字元*產生檔案名稱擴充,匹配目前的目錄下的所有檔案。 for通過命令列來傳遞指令碼中for迴圈列表參數
#!/bin/bashecho "number of arguments is $#"echo "What you input is: "for argument in "$@"do echo "$argument"done
$#表示參數的個數,$@表示參數列表而$*則把所有的參數當作一個字串顯示。
(3)不帶列表for迴圈
由使用者制定參數和參數的個數,與上述的for迴圈列表參數功能相同。
#!/bin/bashecho "number of arguments is $#"echo "What you input is: "for argumentdo echo "$argument"done
比上述代碼少了 $@參數列表,$*參數字串。
(4)類C風格的for迴圈
也被稱為計次迴圈
#!/bin/bashfor((integer = 1; integer <= 5; integer++))do echo "$integer"done
for中第一個運算式(integer = 1)是迴圈變數賦初值的語句,第二個運算式(integer <= 5)決定是否進行迴圈的運算式,退出狀態為非0時將退出for迴圈執行done後的命令(與C中的for迴圈條件是剛好相反的)。第三個運算式(integer++)用於改變迴圈變數的語句。
Sheel中不運行使用非整數類型的數作為迴圈變數,迴圈條件被忽略則預設的退出狀態是0,for((;;))為死迴圈。
類C的for迴圈計算1~100內所有的奇數之和。
#!/bin/bashsum=0for(( i = 1; i <= 100; i = i + 2 ))do let "sum += i"doneecho "sum=$sum"
2、while迴圈
也稱為前測試迴圈語句,重複次數是利用一個條件來控制是否繼續重複執行這個語句。為了避免死迴圈,必須保證迴圈體中包含迴圈出口條件即運算式存在退出狀態為非0的情況。
(1)計數器控制的while迴圈
#!/bin/bashsum=0i=1while(( i <= 100 ))do let "sum+=i" let "i += 2" doneecho "sum=$sum"
指定了迴圈的次數500,初始化計數器值為1,不斷測試迴圈條件i是否小於等於100。在迴圈條件中設定了計數器加2來計算1~100內所有的奇數之和。
(2)結束標記控制的while迴圈
設定一個特殊的資料值(結束標記)來結束while迴圈。
#!/bin/bashecho "Please input the num(1-10) "read numwhile [[ "$num" != 4 ]]do if [ "$num" -lt 4 ] then echo "Too small. Try again!" read num elif [ "$num" -gt 4 ] then echo "To high. Try again" read num else exit 0 fidone echo "Congratulation, you are right! "
例:通過結束標記控制實現階乘的操作
#!/bin/bashecho "Please input the num "read numfactorial=1while [ "$num" -gt 0 ]do let "factorial= factorial*num" let "num--"doneecho "The factorial is $factorial"
(3)標誌控制的while迴圈
使用使用者輸入的標誌值來控制迴圈的結束(避免不知道迴圈結束標誌的條件)。
#!/bin/bashecho "Please input the num "read numsum=0i=1signal=0while [[ "$signal" -ne 1 ]]do if [ "$i" -eq "$num" ] then let "signal=1" let "sum+=i" echo "1+2+...+$num=$sum" else let "sum=sum+i" let "i++" fidone
標誌控制的while迴圈求1~n的累加和,迴圈變數值小於100執行else累加同時迴圈變數加1,直到迴圈變數值等於100將標誌值設定為1,並輸出。
標誌控制的while迴圈與結束標記控制的while迴圈的區別是使用者無法確定無法確定結束標誌,只能程式運行後確定結束標誌。兩者也可以相互轉化。
(4)命令列控制的while迴圈
使用命令列來指定輸出參數和參數個數,通常與shift結合使用,shift命令使位置變數下移一位($2代替$1、$3代替$2,並使$#變數遞減),當最後一個參數顯示給使用者,$#會等於0,$*也等於空。
#!/bin/bashecho "number of arguments is $#"echo "What you input is: "while [[ "$*" != "" ]]do echo "$1" shiftdone
迴圈條件可以改寫為while[[ "$#" -ne 0 ]],等於0時退出while迴圈
3、until迴圈
until命令和while命令類似,while能實現的指令碼until同樣也可以實現,但區別是until迴圈的退出狀態是不為0,退出狀態是為0(與while剛好相反),即whie迴圈在條件為真時繼續執行迴圈而until則在條件為假時執行迴圈。
#!/bin/bashi=0until [[ "$i" -gt 5 ]] #大於5do let "square=i*i" echo "$i * $i = $square" let "i++"done
4、迴圈嵌套
一個迴圈體內又包含另一個完整的迴圈結構,在外部迴圈的每次執行過程中都會觸發內部迴圈,for、while、until可以相互嵌套。
(1)嵌套迴圈實現九九乘法表
#!/bin/bashfor (( i = 1; i <=9; i++ ))do for (( j=1; j <= i; j++ )) do let "temp = i * j" echo -n "$i*$j=$temp " done echo "" #output newlinedone
(2)for迴圈嵌套實現*圖案排列
#!/bin/bashfor ((i=1; i <= 9; i++))do j=9; while ((j > i)) do echo -n " " let "j--" done k=1 while ((k <= i)) do echo -n "*" let "k++" done echo ""done
外層for迴圈嵌套了兩個內層while迴圈,先列印空格在列印*號形成圖案。
5、迴圈控制符break和continue
若須退出迴圈可使用break迴圈控制符,若退出本次迴圈執行後繼續迴圈可使用continue迴圈控制符。
(1)break
在for、while和until迴圈中break可強行退出迴圈,break語句僅能退出當前的迴圈,如果是兩層迴圈嵌套,則需要在外層迴圈中使用break。
#!/bin/bashsum=0for (( i=1; i <= 100; i++))do let "sum+=i" if [ "$sum" -gt 1000 ] then echo "1+2+...+$i=$sum" break fidone
(2)continue
在for、while和until中用於讓指令碼跳過其後面的語句,執行下一次迴圈。continue用於顯示100內能被7整除的數。
#!/bin/bashm=1for (( i=1; i < 100; i++ ))do let "temp1=i%7" #被7整除 if [ "$temp1" -ne 0 ] then continue fi echo -n "$i " let "temp2=m%7" #7個數字換一行 if [ "$temp2" -eq 0 ] then echo "" fi let "m++"done
6、select結構
select結構從技術角度看不能算是迴圈結構,只是相似而已,它是bash的擴充結構用於互動式菜單顯示,功能類似於case結構比case的互動性要好。
(1)select帶參數列表
#!/bin/bashecho "What is your favourite color? "select color in "red" "blue" "green" "white" "black"do breakdoneecho "You have selected $color"
(2)select不帶參數列表
該結構通過命令列來傳遞參數列表,由使用者自己設定參數列表。
#!/bin/bashecho "What is your favourite color? "select colordo breakdoneecho "You have selected $color"
三、總結
(1)迴圈結構中相互嵌套組成更複雜的流程,並結合break和continue可以實現很多複雜的運算。
(2)可以結合其他語言的文法有助於更好的理解迴圈結構。
(3)熟練應用還需要大量的重複練習,重寫優秀的shell代碼也是一種很好的方式。