目標: ????重複的執行一段命令列表。 控制; ????基於一個關鍵命令的返回值。 三種格式: ??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
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]???????????????? 中止這個程序