目標: 完成這一章,你將能夠作以下事情: 使用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語句執行時發生語法錯誤。shell編程之循環語句(1) 目標: 完成這一章,你將能夠作以下事情: 使用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語句執行時發生語法錯誤。