歡迎您光臨本站 註冊首頁

shell編程-循環語句

←手機掃碼閱讀     火星人 @ 2014-03-24 , reply:0

目標:

完成這一章,你將能夠作以下事情:
使用while語句在條件為真的時候重複地執行一段代碼。
使用until語句重複執行一段代碼直到條件為真。
使用交互性的for語句進行循環控制。

1.循環的簡單介紹

目標: ????重複的執行一段命令列表。
控制; ????基於一個關鍵命令的返回值。
三種格式: ??while ... do ... done
??????? until ... do ... done
??????? for ... do ... done
循環語句讓你可以重複執行一個命令列表,而決定是繼續循環還是跳出循環是基於一個命令的返回值。test命令常常被用來控制一個循環是否繼續。
與分支語句不同的是,在分支語句中開始一個分支語句的關鍵字和結束一個分支語句的關鍵字是相反的(if/fi 和case/esac),循環語句由一個關鍵字和一些條件開始,循環體整個用do/done來包圍起來。

2.使用let來進行算術計算

語法:
let expression or (( expression ))
例子:
$ x=10??????????$ x=12
$ y=2?????????? $ let "x <10"???
$ let x=x+2 ???????$ echo $?
$ echo $x???????? 1
12????????????$ (( x > 10 ))
$ let "x = x / (y+1)" ??$ echo $?
$ echo $x ????????$ 0
4???????????? $ if ((x > 10 ))
$ (( x = x + 1 ))???? > ?then echo x greater
$ echo $x???????? > ?else echo x not greater
5???????????? fi
?????????????x greater
循環語句通常使用一個增長的數字變數來進行控制。使用let命令,可以在shell腳本中使用算術表達式。這個命令允許使用長的整數運算。在上例中,expression代表一個shell變數的算術表達式和能夠被shell識別的操作符,而((? ))可以替let命令。shell能夠識別的表達式如下所示:
操作符?????描述
-????? ??減去
!????? ??邏輯相反
* / %????? 乘,除,餘數
+ - ??????加,減
<= ?>= ??關係比較
== !=????? 等於不等於
=??????? 賦值
括弧能夠被用作改變表達式中計算的順序,就像在
let "x=x/(y+1)"
中一樣
注意雙引號被用來忽略括弧的特殊含義。同樣如果你希望使用空格來分隔操作符和操作符的時候,就必須使用雙引號,或者(( ))語句:
let " x = x + (y / 2)" 或者(( x= x+ (y / 2) ))
當使用邏輯和關係操作符,(!,<=,>=,<,>,++,~=),的時候,shell會返回一個代碼變數,?會反映結果是真還是假,再一次說明,必須使用雙引號來防止shell將大於和小於運算符當作I/O重定向。

3.while語句

重複執行循環體,直到條件為真
語法:
while??????????????
?? list A
do
?? list B
done
例子:
$ cat test_while
X=1
while (( X <= 10 ))
do
??echo hello X is $X
??let X=X+1
done
$ test_while
hello X is 1
hello X is 2
.
.
.
hello X is 10
while語句是shell提供的一種循環機制,當條件為真的時候它允許循環體中的命令(list B)繼續執行。條件判斷是通過list A中最後一個命令的返回值來進行。通常一個test或者let命令被用作控制循環的執行,但是任何命令都能被用來產生一個返回值。上面的例子中使用的是test命令可以用let命令來代替,如下:
$ X=1
$ while [ $x -le 10 ]
> do
> ??echo hello X is $X
>?? let X=X+1
> done
命令執行的過程如下:
1.list A中的命令被執行。
2.如果list A中的最後一個命令的返回值為0(真),執行list B。
3.回到第一步。
4.如果list A中的最後一個命令的返回值不為0(假),跳到下面done關鍵字后的第一個命令。
提醒:注意while循環會無窮執行下去,因為有一些循環的控制命令的返回值永遠為真。
$ cat while_infinite
while
?? true
do
?? echo hello
done
$ while_infinite
hello
hello
.
.
.
ctrl + c

4. while結構舉例

例A:???????????????例B
如果ans為yes就重複執行 ???????????當有命令行參數時重複執行
ans=yes???????????????while (($# != 0 ))
while ??????????????? do
[ "$ans" = yes ] ???????????if test -d $1
do ??????????????????then
??echo Enter a name??????????echo contents of $1;
??read name??????????????ls -F $1
??echo $name >> file.names????? fi
??echo "Continue?"????????? shift
??echo Enter yes or no??????? echo There are $# items
??read ans????????????? echo left on the cmd line
done ????????????????done?
上例是兩個while語句的例子,例A提示用戶輸入,然後對用戶的輸入進行判斷,來決定是否繼續執行循環,例子B中,循環會對命令行中每一個參數進行判斷,如果參數是一個目錄,這個目錄中的內容會被顯示出來。如果這個參數不是一個目錄,程序會跳過。注意shift命令的用法,它允許一個一個存取每一個參數。和while命令一起使用可以使這個循環非常靈活。它不關心參數的個數是1個還是100個,循環會繼續執行直到所有的參數都被存取。
注意,如果你希望循環至少執行一次,就必須進行某些設置。例A中會執行循環體至少一次因為ans已經被設為yes。在例B中,如果程序的執行不帶任何參數($#等於0),這個循環就一次都不會執行。

5.until語句

重複循環直到條件為真為止。
語法:??????例子:
until???????$ cat test_until
?list A????? X=1
do???????? until (( x > 10 ))
?list B????? do
done?????????echo hello X is $X
???????????let X=X+1
????????? done
????????? $ test_until
????????? hello X is 1
????????? hello X is 2
????????? hello X is 3
???????????.
???????????.
???????????.
????????? hello X is 10
until語句是shell提供的另一種循環機制,它會持續執行命令(list B)直到一個條件為真為止。同while循環類似,條件判斷由list A中的最後一條命令的返回值來決定的。
命令的執行過程如下:
1.list A中的命令被執行。
2.如果list A中最後一條命令的返回值為非0(假),執行list B。
3.返回到第一步。
4.如果list A中的最後一條命令的返回值為0(真),跳到done關鍵字后的第一條命令。
注意:until循環的無窮執行下去,因為有些循環語句中的控制語句的返回值始終為假。
$ x=1
$ until
> [ $ x -eq 0 ]
> do
> echo hello
> done
hello
hello
hello
.
.
.
ctrl + c

6.until的例子

例A???????????????例B
重複執行循環體直到ans為no為止 ???????重複執行循環直到沒有命令行參數為止
ans=yes?????????????? until (( $# == 0 ))
until ? ????????????? do
? [ "$ans" = no ] ????????? if test -d $1
do ????????????????? then
echo Enter a name??????????? echo context of $1;
?read name ??????????????ls -F $1
?echo $name >> file.names??????fi
?echo "Continue?"??????????shift
?echo Enter yes or no????????echo There are $# items
?read ans ????????????? echo left on the cmd line.
done????????????????done
上例的結構與while語句中的例子類似,但是使用until語句來。注意在兩種語句的test條件的邏輯關係是相反的。
同時請注意用戶輸入的敏感性由一些輕微的變化。使用while語句,只有用戶的輸入的字元串為「yes」時循環才會執行,繼續執行循環的條件十分嚴格,使用until語句,循環會在用戶使用與no不同的任何字元時都會執行。它對於繼續進行循環的條件不太嚴格,你也許希望在決定那一種結構最符合你的要求的時候考慮這一特徵。
預定義ans變數的值不再是必須的,因為它的值會被初始化為NULL,由於NULL不等於no,test會返回假,而循環會被執行。你僅僅需要將$ans用括弧引起來,以免在test語句執行時發生語法錯誤。

7.for語句

對列表的每一條目都進行一次循環過程
,每完成一次循環過程就將var賦予列表中下一個條目,直到完成最後一個條目的循環為止
語法: ???????????例子:
for var in list????????$ cat test_for
do?????????????? for X in 1 2 3 4 5
???list A????????? do
done????????????? echo "2 * $X is c"
??????????????? let X=X*2
??????????????? echo $X
??????????????? done
??????????????? $ test_for
??????????????? 2 * 1 is 2
??????????????? 2 * 2 is 4
??????????????? 2 * 3 is 6
??????????????? 2 * 4 is 8
??????????????? 2 * 5 is 10
在上例中,關鍵字為for,in,do和done,var代表一個shell變數的名字,這個變數的賦值會貫穿for循環的執行過程中,list是一串由空格或者tab分割開的字元串,在每一次循環執行都要將一個串賦值給var。
for循環的執行過程如下:
1.shell變數var被設置等於list中的第一個字元。
2.list A中的命令會被執行。
3.shell變數var被設置等於list中下一個字元。
4.list A中的命令被執行。
5.循環會持續執行,直到每一個list中的條目都執行過循環為止。

8.for循環的例子

例A:
$ cat example_A
for NAME in $(grep home /etc/passwd | cut -f1 -d:)
do
??mail $NAME < mtg.minutes
??echo mailed mtg.minutes to $NAME
done
例B
$ cat example_B
for FILE in *
do
?if
??test -d $FILE
?then
??ls -F $FILE
?fi
done
for結構是一種非常靈活的循環結構,它能夠讓循環貫穿任何能產生的列表。使用命令替代可以很容易產生生成列表,就像第一個例子使用管道和過濾器可以產生一個列表。如果你要求多次存取相同的列表,你也許想要將它存儲到個文件中。你可以使用cat命令來為你的for循環產生列表,正如下例所示:
??$ cat students
??user1
??user2
??user3
??user4
??$ cat for_student_file_copy
??for NAME in $(cat students)
??do
??cp test.file /home/$NAME
??chown $NAME /home/$NAME/test.file
??chmod g-w,o-w /home/$NAME/test.file
??echo done $NAME
??done
??$
存取命令行參數
你可以從命令行參數來產生list:
for i in $*?????????或者?????for i
do???????????????????? do?
??cp $i $HOME/backups????????????cp $i $HOME/backups
done ???????????????????done

9.break,continue,和exit命令

break [n] ?????中止循環過程的執行,並且跳到下一個命令。
continue [n]????停止循環過程的當前一個反覆並且跳到循環中的下一個反覆過程的開始部分
exit [n] ????? 停止shell程序的執行,並且將返回值設置為n。
在許多情況下,你可能需要在循環的正常中止條件滿足之前放棄一個循環的執行。break和continue命令提供了一種無條件的流程式控制制,通常用在遇到一個錯誤的情況下來中止當前的循環。而exit命令用在不能從某種情況下恢復出來而必須中止整個程序的運行的時候。
break命令會中止循環並且將控制權傳遞到done關鍵字後面的第一個命令。結果是完全跳出這個循環體而繼續執行下面的命令。
continue命令有一點不同。當在程序執行過程中遇到這個命令,就會忽略本次循環中剩餘的命令,而將控制權交給循環的頂部。這樣,continue命令能讓你僅僅中止所有循環中的一個循環過程而繼續從當前循環的頂部開始執行。
在while和until循環中,這種處理(continue)會導致在初始列表的開始部分繼續執行,在for循環中,會將變數設置為列表中的下一個條目,然後繼續執行循環。
exit命令停止執行當前的shell程序,並且根據提供的參數為這個shell程序設置一個返回值,如果沒有提供返回值參數,當前的shell程序的返回值會被設置為在exit命令之前執行的命令的返回值。
注意:循環的流程式控制制在正常的情況下應當是通過設置循環開始部分的條件(while,until),或者是列表中的條目都循環完的(for),的情況來結束循環。而對循環過程進行中斷操作僅僅應當在循環執行期間遇到沒有規律的或者是錯誤的條件的時候才應當使用。

10.break和continue的例子

while
??true
do
??echo "Enter file to remove: c"
??read FILE
??if test ! -f $FILE
??then
????echo $FILE is not a regular file
????continue
??fi
??echo removing $FILE
??rm $FILE
??break
done
這個例子顯示break和continue命令的一次有效的使用。這個命令的執行是在while循環的test條件為真的情況下,會始終產生一個為真的結果;這意味著這個循環會是一個無限的循環,除非循環體中的某些命令能中止循環的運行(這就是bread命令需要做的)。如果輸入的文件不是一個普通文件,一個錯誤信息會列印,同時continue命令會提醒用戶再輸入一次文件名。如果這個文件是個普通的文件,它會被刪除,並且break命令被用來跳出這個無窮循環。

11.shell編程之循環-總結

let expression ?????????????計算一個算術表達式
((expression)) ?????????????計算一個算術表達式
while condition is true do ...done??? while
until condition is true do ... done???until
for var in list do ... done ?????? for
break [n]????????????????break out of loop
continue [n]?????????????? 中止當前循環中的一次循環過程
exit [n]???????????????? 中止這個程序

[火星人 ] shell編程-循環語句已經有599次圍觀

http://coctec.com/docs/linux/show-post-135633.html