1. 程式人生 > >第三章:shell結構化命令 for & while迴圈

第三章:shell結構化命令 for & while迴圈

for 命令 當你需要重複一組命令直至達到某個特定的條件,比處如處理某個目錄下的所有檔案、系統上的所有使用者或是某個文字檔案中的所有行。 for 的基本格式     for var in list     do       commands      done 在list引數中,你提供了迭代中要用的一系列的值。你可以通過幾種不同的途徑來制定列表中的值。 在 do 和 done 語句之間輸入的命令可以是一條或者多條標準的shell 命令,在這些命令中$var變數 包含著這次迭代對應的當前那個列表中的值。 說明: 只要你願意,也可以將do 語句和for 語句放在同一行,但必須用分號將其同列表中的值分開: for var in list : do
for 最基本的用法就是遍歷for 命令自身中定義的一系列值: [[email protected] ~]# vim test27 #!/bin/bash # basic for command for test in  zhengwei yagnman oracle root mysql sqlser  do    echo  the next state is $test done [[email protected] ~]# sh test27 the next state is zhengwei the next state is yagnman the next state is oracle
the next state is root the next state is mysql the next state is sqlser 每次 for 命令遍歷提供的值列表時,它會將列表中的下一個值賦給$test變數像for 命令語句中的任何其他指令碼變數一樣使用 。在最後一次迭代後, $test變數的值會在shell指令碼中的剩餘部分一直保持有效。它會一直保持到最後一次迭代的值(除非你修改了它) [[email protected] ~]#vim test28 #!/bin/bash # testing the for variable after the looping for test in zhengwei yangman oracle mysql sqlserver
do    echo "the next state is $test" done    echo  "the last state we visited was $test" test=mongodb echo "wait. now we're visiting $test" [[email protected] ~]# sh test28 the next state is zhengwei the next state is yangman the next state is oracle the next state is mysql the next state is sqlserver the last state we visited wassqlserver wait. now we're visitingmongodb test 變數保持了它的值,也允許我們修改它的值並在for 迴圈之外跟其他變數一樣使用 讀取列表中的複雜值 [[email protected] ~]#vim test29 #!/bin/bash #another example of how not to use the  for command for test in  i don't know if this'll work do    echo "work:$test" done [[email protected] ~]# sh test29 work:i work:dont know if thisll work:work shell 看到了列表值中的單引號並嘗試使用他們來定義一個單獨的資料值,整個過程是混亂的 有兩個辦法解決這個問題 使用轉義字元(反斜線)來將單引號轉義; 使用雙引號來定義用到單引號的值 [[email protected] ~]# vim test30 #!/bin/bash # another example of how not to use the command for test in I don\'t  know if "this'll" work do    echo "work:$test" done [[email protected] ~]# sh test30 work:I work:don't work:know work:if work:this'll work:work 在第一個有問題的值上,添加了反斜槓字元來轉義don't值中的單引號,第二個有問題的值上,將this'll 用 雙引號圈起來。兩種方法都成正常 你可能遇到的另一個問題是有多個詞的值,記住,for 迴圈假定每個值都是用空格分隔的。如果保護空格的資料值,你可能遇到一下問題 [[email protected] ~]# vim test 31 #!/bin/bash #another example of how not to use the for command for test in zhu shan zhu ping shiyan hubei do     echo "now going to $test" done [[email protected] ~]# sh test31 now going to zhu now going to shan now going to zhu now going to ping now going to shiyan now going to hubei 這不是我們想要的結果。for命令用空格來劃分列表中的每一個值。如果在單獨的資料值中有空格,那麼你必須用引號來將這些值圈起來 [[email protected] ~]# vim  test32 #!/bin/bash # an example of how to properly define values for  test in "zhu shan" "zhu ping" shiyan hubei do     echo "now going to $test" done [[email protected] ~]# sh test32 now going to zhu shan now going to zhu ping now going to shiyan now going to hubei 注意:當你某個值兩邊有雙引號時,shell不會將雙引號當成值的一部分。 從變數讀取列表 通常shell指令碼遇到的情況是,你將一系列值都集中在了一個變數中,然後需要遍歷整個列表。 [[email protected] ~]#vim test33 #!/bin/bash #using a variable to hold the list list="zhengwei yagnman oracle mysql" list=$list"Connecticut" for state in $list do    echo "have you ever visited $state?" done [[email protected] ~]# sh test33 have you ever visited zhengwei? have you ever visited yagnman? have you ever visited oracle? have you ever visited mysql? have you ever visited Connecticut? 注意:還用了另一個賦值語句來向$list變數包含的已有的列表添加了一個值。這是向變數中儲存的已有的文字字串尾部新增文字的一個常用方法。 從命令讀取值 生成列表中要用的值的另外一個途徑就是使用命令的輸出。你可以使用反引號 來執行任何產生輸出的命令,然後在for迴圈中使用該命令輸出 [[email protected] ~]#vim  test34 #!/bin/bash #reading values from a file file="states" for state in `cat $file` do   echo "visit beautiful $state" done [[email protected] ~]# cat states zhengwei yangman oracle mysql mongodb [[email protected] ~]# sh test34 visit beautiful zhengwei visit beautiful yangman visit beautiful oracle visit beautiful mysql visit beautiful mongodb 更改文欄位分隔符 這個問題的原因是特殊的環境變數IFS,稱為內部欄位分隔符, IFS環境變數定義了shell 用作欄位分隔符的一系列字串。預設情況下, shell 會將下列字元當做欄位分隔符: 空格 製表符 換行符 可以在shell指令碼中臨時更改IFS環境變數的值來限制一下被shell當坐欄位分隔符 的字元。如果你修改的IFS的值使其只能識別換行符,你必須這麼做: IFS=$'\n' 將這個語句加入到指令碼中,告訴shell在資料中忽略空格和製表符。 對當前一個指令碼使用這種方法,將獲得如下輸出 [[email protected] ~]#vim test35 #!bin/bash # reding values from a file file="state" IFS=$'\n' for state in `cate $file` do   echo "visit beautiful $state" done [[email protected] ~]# sh test35 visit beautiful zhengwei visit beautiful yangman visit beautiful oracle visit beautiful mysql visit beautiful mongodb visit beautiful zhu shuan visit beautiful zhu ping 現在shell指令碼能夠使用列表中含有空格的值了 警告: 在處理長指令碼時,可能在一個地方需要修改IFS的值,然後忘掉它了並在指令碼其他地方以為還是預設的值。一個可以參考的簡單實踐是在改變IFS之前儲存原來的IFS值,之後再恢復它 這一這樣寫   IFS.OLD=$IFS   IFS=$'\n'   <use the new IFS value in code>   IFS=$IFS.OLD 這會為指令碼中後面的操作保證IFS的值恢復到了預設值 還有其他一些IFS環境變數的絕妙用法,假設你要遍歷一個檔案中用冒號分隔的值 (比如在/etc/passwd檔案中)你要做的就是將IFS的值設為冒號: IFS=: 如果你要指定多個IFS字元,只要將它們在賦值行串起來就行: IFS=$'\n:;" 這個賦值會將換行符、冒號、分號和雙引號作為欄位分隔符。如何使用IFS字元解析資料沒有任何限制 用萬用字元讀取目錄 可以用for命令來自動遍歷滿是檔案的目錄。進行操作時,必須在檔名或路經中使用萬用字元。 它會強制shell使用檔案擴充套件匹配(file globbing)。檔案擴充套件匹配是生成匹配製定的萬用字元的檔名 或路徑名的過程。 這個特性在處理目錄中檔案而你不知道所有的檔名時非常好用: [[email protected] ~]# vim test36 #!/bin/bash # iterate through all the file in a direcotry for file in /* do   if [ -d "$file" ]   then       echo "$file is a directory"   elif [ -f "$file" ]   then       echo "$file is a file"    fi done [[email protected] ~]# sh test36 /bin is a directory /boot is a directory /dev is a directory /proc is a directory /rlwrap-0.30 is a directory /rlwrap-0.30.tar is a file /root is a directory /sbin is a directory /selinux is a directory /srv is a directory /sys is a directory /test14 is a file /test26 is a file for迴圈比遍歷/*輸出結果。 注意:在這個例子中,我們用if語句裡的測試處理的有些不同 if [ -d "$file" ] 在linux中,目錄名和檔名是可以有空格的。要容納這種值,你應該將$file遍歷用雙引號圈起來。 如果不這麼做,遇到含有空格的目錄或檔名時會有錯誤產生: 你也可以在for命令中通過列出一系列的目錄萬用字元來將目錄查詢方法和列表方法合併進同一個語句: c語言風格的for命令 [[email protected] ~]#vim test37 #!/bin/bash #testing the c-style for loop for ((i=1; i<=10;i++)) do   echo "the next number is $i" done [[email protected] ~]# sh test37 the next number is 1 the next number is 2 the next number is 3 the next number is 4 the next number is 5 the next number is 6 the next number is 7 the next number is 8 the next number is 9 the next number is 10 使用多個變數 [[email protected] ~]#vim test38 #!/bin/bash #multiple variables for(( a=1, b=10; a<=10;a++,b-- )) do   echo "$a - $b " done [[email protected] ~]# sh test38 1 - 10 2 - 9 3 - 8 4 - 7 5 - 6 6 - 5 7 - 4 8 - 3 9 - 2 10- 1 while 命令 while 命令某種意義上是if-then語句和for迴圈的混雜體。while命令允許你定義一個要測試的 命令,然後迴圈執行一組命令,只要定義的測試命令返回的狀態碼0;他會在每個迭代的一開始測試 test命令。在test命令返回非0退出狀態碼時,while命令會停止執行那組命令 while 的基本格式 while  test command do   other commands done while命令的關鍵是,指定的test命令的退出狀態碼必須隨著迴圈中執行的命令改變如果退出狀態碼從來不變,那while迴圈將會一直不停地迴圈 最常見的test命令的用法是,用方括號來檢視迴圈命令中用到shell變數的值: [[email protected] ~]#vim test39 #!/bin/bash # while command test var1=10 while [ $var1 -gt 0 ] do   echo $var1   var1=$[ $var1 - 1 ] done [[email protected] ~]# sh test39 10 9 8 7 6 5 4 3 2 1 while [ $var1 -gt 0 ] 只有測試條件成立,while命令才會繼續遍歷執行定義好的命令。 測試條件中用到的變數必須被修改,否則你就進入了一個無限迴圈。 本例中,我們用shell算術來將變數值減一:  var1=$[ $var1 - 1 ] while 迴圈會在測試條件不再成立時停止 使用多個測試命令  在極少數情況下,while命令允許你在while語句行定義多個測試命令。  只有最後一個測試命令的退出狀態碼會被用來決定什麼時候結束迴圈。 [[email protected] ~]#vim test40 #!/bin/bash # testing a multicommand while loop var1=10 while echo $var1   [ $var1 -ge 0 ] do   echo "this is inside the loop"   var1=$[ $var1 - 1 ] done [[email protected] ~]# sh test40 10 this is inside the loop 9 this is inside the loop 8 this is inside the loop 7 this is inside the loop 6 this is inside the loop 5 this is inside the loop 4 this is inside the loop 3 this is inside the loop 2 this is inside the loop 1 this is inside the loop 0 this is inside the loop -1 while語句中定義了兩個測試命令  while echo $var1   [ $var1 -ge 0 ] 第一個測試簡單的顯示var1變數的當前值, 第二個方括號來決定變數的值,在迴圈內部,echo 語句會顯示一條簡單的訊息說明迴圈被執行了。 until 命令 until命令和while命令工作方式完全相反,until命令要求你指定一個通常輸出非0退出狀態碼的測試命令。 只有測試退出狀態碼非0,shell才會指定迴圈中列出的那些命令。一旦測試命令返回狀態碼是0,迴圈就結束了 until命令格式如下  until test commands  do    other commands  done 類似與while命令,你可以在until命令語句中有多個測試命令,只有最後一個退出狀態碼決定shell是否執行定義好的其他命令 vim test41 #!/bin/bash # using the until command var1=100 until [ $var1 -eq 0 ] do   echo var1   var1=$[ $var1-25 ] done [[email protected] ~]# sh test41 100 75 50 25 until 使用多個測試命令是要注意 vim test42 #!/bin/bash #using the until command var1=100 until echo $var1   [ $var1 -eq 0 ] do   echo inside the loop:$var1   var1=$[ $var1 - 25 ] done [[email protected] ~]# sh test42 100 inside the loop:100 75 inside the loop:75 50 inside the loop:50 25 inside the loop:25 0 +6 3 巢狀迴圈 迴圈語句可以在迴圈內使用任意型別的命令,包括其他迴圈命令。 這種稱為巢狀迴圈。 注意,在使用巢狀迴圈時,你是在迭代中使用迭代,命令列的次數是乘積關係。 vim test43 #!/bin/bash # nesting for loops for (( a=1; a<=3; a++ )) do echo "starting loop $a" for (( b=1; b<=3; b++ )) do   echo " inside loop :$b" done [[email protected] ~]# sh test43 starting loop 1  inside loop :1  inside loop :2  inside loop :3 starting loop 2  inside loop :1  inside loop :2  inside loop :3 starting loop 3  inside loop :1  inside loop :2  inside loop :3 在混用迴圈命令時也一樣,比如在while迴圈內部紡織一個for迴圈 [[email protected] ~]#vim test44 #!/bin/bash # placing a for loop inside a while loop var1=5 while [ $var1 -ge 0 ]  do    echo "outer loop:$var1"    for (( var2=1; var2<3; var2++ ))    do      var3=$[ $var1 * $var2 ]      echo " Inner loop: $var1 * $var2 = $var3"    done    var1=$[ $var1 - 1 ] done [[email protected] ~]# sh test44 outer loop:5  Inner loop: 5 * 1 = 5  Inner loop: 5 * 2 = 10 outer loop:4  Inner loop: 4 * 1 = 4  Inner loop: 4 * 2 = 8 outer loop:3  Inner loop: 3 * 1 = 3  Inner loop: 3 * 2 = 6 outer loop:2  Inner loop: 2 * 1 = 2  Inner loop: 2 * 2 = 4 outer loop:1  Inner loop: 1 * 1 = 1  Inner loop: 1 * 2 = 2 outer loop:0  Inner loop: 0 * 1 = 0  Inner loop: 0 * 2 = 0  shell 能夠區分開內部的for迴圈的do和done命令和外部while迴圈的do和done命令。甚至可以混用 until 和 while 迴圈 [[email protected] ~]# test45 #!/bin/bash # using until and while loops var1=3   until [ $var1 -eq 0 ]   do     echo "outer loop: $var1"   var2=1   while [ $var2 -lt 5 ]   do     var3=`echo "scale=4; $var1 / $var2" |bc`          echo " inner loop: $var1 / $var2 = $var3"          var2=$[ $var2 + 1 ]   done   var1=$[ $var1 - 1 ]  done [[email protected] ~]# sh test45 outer loop: 3  inner loop: 3 / 1 = 3.0000  inner loop: 3 / 2 = 1.5000  inner loop: 3 / 3 = 1.0000  inner loop: 3 / 4 = .7500 outer loop: 2  inner loop: 2 / 1 = 2.0000  inner loop: 2 / 2 = 1.0000  inner loop: 2 / 3 = .6666  inner loop: 2 / 4 = .5000 outer loop: 1  inner loop: 1 / 1 = 1.0000  inner loop: 1 / 2 = .5000  inner loop: 1 / 3 = .3333  inner loop: 1 / 4 = .2500 外部的until迴圈以值3開始並繼續執行直到等於0.內部while迴圈會以值1開始並執行下去, 只要值小於5.每個迴圈都必須改變在測試條件中用到的值,否則迴圈就會無休止的進行下去。 迴圈處理檔案資料   通常你必須遍歷儲存在檔案中的資料。   使用巢狀迴圈;   修改IFS環境變數   通過修改IFS環境變數,就能強制for命令將檔案中的每一行都當成一個條目來處理,   即便資料中有空格也是如此。一旦你從檔案中提取了單獨行,你可能需要再次迴圈來   取其中的資料。    經典的例子是處理 /etc/passwd檔案中的資料。這要求逐行遍歷/etc/passwd檔案,並將    IFS變數的值改成冒號,這樣你就能分隔開每行中的各個單獨的資料段了。 [[email protected] ~]#vim test46 #!/bin/bash #changing the IFS value IFS.OLD=$IFS IFS=$'\n' for entry in `cat /etc/passwd` do    echo "values in $entry -"   IFS=:   for value in $entry   do     echo "    $value"   done done [[email protected] ~]# sh test46 values in root:x:0:0:root:/root:/bin/bash -     root     x     0     0     root     /root     /bin/bash values in bin:x:1:1:bin:/bin:/sbin/nologin -     bin     x     1     1     bin     /bin     /sbin/nologin values in daemon:x:2:2:daemon:/sbin:/sbin/nologin -     daemon     x     2     2     daemon     /sbin     /sbin/nologin values in adm:x:3:4:adm:/var/adm:/sbin/nologin - 外層迴圈處理一行的值,內層迴圈處理每行的單讀個值 控制迴圈 有幾個命令可以控制迴圈內部的情況: break 命令 continue命令 break 命令 break 命令是退出進行中的迴圈的一個簡單的方法。你可以使用break命令來退出 任意型別的迴圈,包括while 和until迴圈 1. 跳出單個迴圈 在shell執行break命令時,它會跳出正在處理的迴圈: [[email protected] ~]#vim test47 #!/bin/bash # breaking out of a for  loop for var1 in 1 2 3 4 5 6 7 8 9 10 do   if      [ $var1 -eq 5 ]   then      breal   fi   echo "Iteration number: $var1" done echo "the for loop is completed" [[email protected] ~]# sh test47 Iteration number: 1 Iteration number: 2

相關推薦

shell結構命令 for & while迴圈

for 命令 當你需要重複一組命令直至達到某個特定的條件,比處如處理某個目錄下的所有檔案、系統上的所有使用者或是某個文字檔案中的所有行。 for 的基本格式     for var in list

玩轉資料結構——最基礎的動態資料結構連結串列

內容概括: 3-1.什麼是連結串列 3-2.在連結串列中新增元素 3-3.使用連結串列的虛擬頭結點 3-4.連結串列的遍歷,查詢和修改 3-5.從連結串列中刪除元素 3-6.使用連結串列實現棧 3-7.帶有尾指標的連結串列:使用連結串列實現佇列

易學筆記-go語言-4基本結構和基本資料型別/4.4 變數/4.4.3 函式體內最簡單的變數初始

函式體內最簡單的變數賦值 格式:  變數名 := 值 舉例: var goos string = os.Getenv("GOOS") fmt.Printf("The operating system is: %s\n", goos) //函式體內最

易學筆記-go語言-4基本結構和基本資料型別/4.4 變數/4.4.4 函式體內並行初始

函式體內並行賦值 在 第4章:基本結構和基本資料型別/4.4 變數/4.4.3 函式體內最簡單的變數賦值基礎上,多個變數同時賦值 舉例: 程式碼: a, b, c := 5, 10, "易學筆記"     fmt.Printf("a&n

python專案的結構和包的建立

python專案的結構和包的建立 在python的圈子裡,有許多人無償得公開自己開發的程式庫,使用者可以通過pip 命令來安裝這些庫,我們在釋出時需要將其建立成一種特殊的檔案,這種檔案就是程式包,我們將會在本節學到程式包的製作流程: python專案目

部分 管理篇 MongoDB shell之系統命令、使用者命令

[[email protected] bin]# ./mongo MongoDB shell version: 2.6.6 connecting to: test > help         db.help()                    help on db methods #資

Redis命令

字串Redis字串可以儲存三種類型的值:位元組串,整數,浮點數。使用者可以通過給定一個任意的數值,對儲存著整數或者浮點數的字串執行自增或者自減操作,有需要的時候,Redis還會將整數轉換成浮點數。Redis中的自增和自減命令INCR:  INCR key-name     將

【算法競賽入門經典—訓練指南】學習筆記(含例題代碼與思路)實用數據結構

其他 ont freopen data 依然 插入 else if swa urn 值得註意的是,本章雖然依然有很多不錯的思想和題目,但並不建議初學知識點時從這裏入門。並不是因為題目難,而是講解並沒有看網上其他博客來的清楚。 本章缺少的重要科技:\(Link-Cut-Tre

《Java從入門到失業》基礎語法及基本程式結構(四)基本資料型別(字元編碼和char型)

3.6.4字元編碼        咦?怎麼好像有東西亂入了?不是講基本資料型別麼?哈哈,因為還剩下最後一個char型了,因為char型會牽涉到Unicode編碼相關,因此我決定先科普一下字符集編碼。     &

《Java從入門到失業》基礎語法及基本程式結構(五)基本算數運算子(1)

3.7運算子       數學運算是計算機的基本用途之一,Java提供了非常豐富的運算子來支援。我們根據運算的特點和性質,把運算子劃分為幾組:基本算數運算子、自增自減運算子、關係運算符、位運算子、邏輯運算子、賦值運算子、其他運算子。下面分別介紹。 3.7.1基本算數運算子 &nb

《Java從入門到失業》基礎語法及基本程式結構(3.7)運算子(小數二進位制、科學記數法、IEEE754標準)

3.7.1.4浮點數運算        要討論浮點數運算,牽涉到的知識比較多,下面一點一點的來逐步展開。為了便於同時討論十進位制和二進位制數,我們做一個約定,我們把十進位制數簡寫為N10,把二進位制數簡寫為N2。 3.7.1.4.1小數的二進位制 &

《Java從入門到失業》基礎語法及基本程式結構(3.8)流程控制(選擇語句、if-else語句、switch語句)

3.8流程控制        到此為止,我們已經基本瞭解了Java的基礎語法,會定義不同型別的變數,會命名,會給變數賦值和運算等。接下來,我們需要學會流程控制方面的知識。 3.8.1選擇語句 3.8.1.1if-else語句   

《Java從入門到失業》基礎語法及基本程式結構(3.8)流程控制(迴圈語句、while語句、for語句)

3.8.2迴圈語句 3.8.2.1while語句        最近這些年買彩票只能去投注站買,早些年,筆者經常是在網上買。在網上買有個功能:追號。就是假如你想一直買同一組號碼,直到中大獎為止。你可以設定一個條件,比如中了頭獎就不繼續買了,如果沒有中頭獎,下一期繼續買同

《Java從入門到失業》基礎語法及基本程式結構(3.9)陣列(陣列基本使用、陣列的迴圈、陣列拷貝、陣列排序、多維陣列)

3.9陣列 3.9.1陣列基本使用        陣列,英文叫Array,是一種資料結構,是用來存放同一資料型別數值的集合。例如存放30個int型數值、存放100個double型數值等等。 我們知道使用一個變數,需要先宣告一個變數,例如:int a;

讀構建之法 軟件工程師的成長

知識點 可維護 vid -s 評估 不同 fun 可靠 科研 本章理論和知識點:評價軟件工程師水平的主要方法 軟件工程把相關的技術和過程統一到一個體系中,叫“軟件開發流程”,軟件開發流程的目的是為了提高軟件開發、運營、維護的效率,以及提升用戶滿意度、軟件的可靠性和可維護性。

8Shell腳本歸檔與壓縮

extract config 生成 -- dir exclude 硬盤分區 txt name 第8章:Shell腳本歸檔與壓縮   定期備份不可小視,我們可以通過shell腳本來實現備份自動化。其中數據備份一般要使用到歸檔與壓縮,歸檔與壓縮對於系統

9Shell腳本進程管理

dstat align 性能 主機名 running auto whatis sighup 發行版本 第9章:Shell腳本進程管理 9.1、進程概念 理解進程概念需要先簡單了解指令和程序這兩個概念,進程跟指令和程序是相關聯的。 什麽叫指

JAVA-初步認識--循環結構的練習2

col 顯示 ole switch語句 認識 選擇 執行 blog spa 一. 對於循環結構while語句的練習 註解:while語句的書寫形式和if格式1的書寫手法很相似,唯一的不同點在於開頭的關鍵字不一樣。以視頻的講解來看,兩者條件語句的判斷標準是一樣的,最終輸出

if選擇結構

als mage 進入 input ima ring ext core equals if基本語法: if(條件){// 表達式 // 代碼塊 } eg: int a = 10; if(a > 1){ System.out.println("內容"); }

基本概念

npr bject 字面量 enume 不能 數據 開頭 clas int() 語法 借鑒了C語言以及類C語言(如java,perl)的語法 區分大小寫 標記符 字母數字下劃線$ 開頭不為數字 嚴格模式 use strict; 語句以分號結尾 關鍵