for var in list
do
commands
done
在每次叠代中,變量var會包含列表中的當前值。第一次叠代會使用列表中的第一個值,第二次叠代使用第二個值,以此類推,直到列表中的所有值都過一遍。
在do和done語句之間輸入的命令可以是一條或多條标準的bash shell命令。在這些命令中,$var變量包含着這次叠代對應的當前列表項中的值。
也可以将do語句和for語句放在同一行,但必須用分号将其同列表中的值分
開:for var in list; do。
13.1.1 讀取列表中的值
每次for命令遍曆值列表,它都會将列表中的下個值賦給$test變量。$test變量可以像for命令語句中的其他腳本變量一樣使用。在最後一次叠代後,$test變量的值會在shell腳本的剩餘部分一直保持有效。它會一直保持最後一次叠代的值(除非你修改了它)。
$test變量保持了其值,也允許我們修改它的值,并在for命令循環之外跟其他變量一樣使用。
13.1.2 讀取列表中的複雜值單引号帶來的問題:
有兩種辦法可解決這個問題:
使用轉義字符(反斜線)來将單引号轉義;
使用雙引号來定義用到單引号的值
for循環假定每個值都是用空格分割的.如果在單獨的數據值中有空格,就必須用雙引号将這些值圈起來。
13.1.3 從變量讀取列表
一系列值都集中存儲在了一個變量中,然後需要遍曆變量中的整個列表。也可以通過for命令完成這個任務。
$list變量包含了用于叠代的标準文本值列表。注意,代碼還是用了另一個賦值語句向$list變量包含的已有列表中添加(或者說是拼接)了一個值。這是向變量中存儲的已有文本字符串尾部添加文本的一個常用方法。
13.1.4 從命令讀取值生成列表中所需值的另外一個途徑就是使用命令的輸出。可以用命令替換來執行任何能産生輸出的命令,然後在for命令中使用該命令的輸出。
這個例子在命令替換中使用了cat命令來輸出文件states的内容。你會注意到states文件中每一行有一個州,而不是通過空格分隔的。for命令仍然以每次一行的方式遍曆了cat命令的輸出,假定每個州都是在單獨的一行上。但這并沒有解決數據中有空格的問題。如果你列出了一個名字中有空格的州,for命令仍然會将每個單詞當作單獨的值。這是有原因的,下一節我們将會了解。
13.1.5 更改字段分隔符造成這個問題的原因是特殊的環境變量IFS,叫作内部字段分隔符(internal field separator)。IFS環境變量定義了bash shell用作字段分隔符的一系列字符。默認情況下,bash shell會将下列字符當作字段分隔符:
空格
制表符
換行符
如果bash shell在數據中看到了這些字符中的任意一個,它就會假定這表明了列表中一個新數據字段的開始。在處理可能含有空格的數據(比如文件名)時,這會非常麻煩
要解決這個問題,可以在shell腳本中臨時更改IFS環境變量的值來限制被bash shell當作字段分隔符的字符。例如,如果你想修改IFS的值,使其隻能識别換行符,那就必須這麼做:
IFS=$'\n'
将這個語句加入到腳本中,告訴bash shell在數據值中忽略空格和制表符。對前一個腳本使用這種方法,将獲得如下輸出。
在處理代碼量較大的腳本時,可能在一個地方需要修改IFS的值,然後忽略這次修改,在
腳本的其他地方繼續沿用IFS的默認值。一個可參考的安全實踐是在改變IFS之前保存原
來的IFS值,之後再恢複它。
這種技術可以這樣實現:
IFS.OLD=$IFS
IFS=$'\n'
<在代碼中使用新的IFS值>
IFS=$IFS.OLD
這就保證了在腳本的後續操作中使用的是IFS的默認值。
還有其他一些IFS環境變量的絕妙用法。假定你要遍曆一個文件中用冒号分隔的值(比如在/etc/passwd文件中)。你要做的就是将IFS的值設為冒号。
IFS=:
如果要指定多個IFS字符,隻要将它們在賦值行串起來就行。
IFS=$'\n':;"
這個賦值會将換行符、冒号、分号和雙引号作為字段分隔符。如何使用IFS字符解析數據沒有任何限制。
13.1.6 用通配符讀取目錄
for命令會遍曆/home/rich/test/*輸出的結果。該代碼用test命令測試了每個條目(使用方括号方法),以查看它是目錄(通過-d參數)還是文件(通過-f參數)
if [ -d "$file" ]
在Linux中,目錄名和文件名中包含空格當然是合法的。要适應這種情況,應該将$file變量用雙引号圈起來
也可以在for命令中列出多個目錄通配符,将目錄查找和列表合并進同一個for語句
13.3 while命令
while命令允許定義一個要測試的命令,然後循環執行一組命令,隻要定義的測試命令返回的是退出狀态碼0。它會在每次叠代的一開始測試test命令。在test命令返回非零退出狀态碼時,while命令會停止執行那組命令。
13.3.1 while的基本格式
while test command
do
other commands
done
while命令的關鍵在于所指定的test command的退出狀态碼必須随着循環中運行的命令而改變。如果退出狀态碼不發生變化, while循環就将一直不停地進行下去。
最常見的test command的用法是用方括号來檢查循環命令中用到的shell變量的值。
13.3.2 使用多個測試命令
while命令允許你在while語句行定義多個測試命令。隻有最後一個測試命令的退出狀态碼會被用來決定什麼時候結束循環.
while語句中定義了兩個測試命令。
while echo $var1
[ $var1 -ge 0 ]
第一個測試簡單地顯示了var1變量的當前值。第二個測試用方括号來判斷var1變量的值。在循環内部,echo語句會顯示一條簡單的消息,說明循環被執行了。注意當你運行本例時輸出是如何結束的。
This is inside the loop
-1
while循環會在var1變量等于0時執行echo語句,然後将var1變量的值減一。接下來再次執行測試命令,用于下一次叠代。echo測試命令被執行并顯示了var變量的值(現在小于0了)。直到shell執行test測試命令,whle循環才會停止。
在含有多個命令的while語句中,在每次叠代中所有的測試命令都會被執行,包括測試命令失敗的最後一次叠代。
注意,每個測試命令都出現在單獨的一行上。
13.4 until命令until命令和while命令工作的方式完全相反。until命令要求你指定一個通常返回非零退出狀态碼的測試命令。隻有測試命令的退出狀态碼不為0,bash shell才會執行循環中列出的命令。一旦測試命令返回了退出狀态碼0,循環就結束了。
until test commands
do
other commands
done
和while命令類似,你可以在until命令語句中放入多個測試命令。隻有最後一個命令的退出狀态碼決定了bash shell是否執行已定義的other commands。
同while命令一樣,在until命令中使用多個測試命令時要注意。
13.5 嵌套循環
循環語句可以在循環内使用任意類型的命令,包括其他循環命令。這種循環叫作嵌套循環(nested loop)。
13.6 循環處理文件數據
通常必須遍曆存儲在文件中的數據。這要求結合兩種技術:
通過修改IFS環境變量,就能強制for命令将文件中的每行都當成單獨的一個條目來處理,即便數據中有空格也是如此。一旦從文件中提取出了單獨的行,可能需要再次利用循環來提取行中的數據。
環境變量IFS,叫作内部字段分隔符(internal field separator)。IFS環境變量定義了bash shell用作字段分隔符的一系列字符。默認情況下,bash shell會将下列字符當作字段分隔符:
如果你想修改IFS的值,使其隻能識别換行符:IFS=$'\n'
将這個語句加入到腳本中,告訴bash shell在數據值中忽略空格和制表符。
例子:處理/etc/passwd文件中的數據。這要求逐行遍曆/etc/passwd文件,并将IFS變量的值改成冒号,這樣就能分隔開每行中的各個數據段了。
在運行這個腳本時,會得到如下輸出。
13.7 控制循環
有兩個命令能幫我們控制循環内部的情況:
可以用break命令來退出任意類型的循環,包括while和until循環。
1. 跳出單個循環在shell執行break命令時,它會嘗試跳出當前正在執行的循環。
for循環通常都會遍曆列表中指定的所有值。但當滿足if-then的條件時,shell會執行break命令,停止for循環。
這種方法同樣适用于while和until循環。
2. 跳出内部循環在處理多個循環時,break命令會自動終止你所在的最内層的循環。
3. 跳出外部循環
有時你在内部循環,但需要停止外部循環。break命令接受單個命令行參數值:
break n
其中n指定了要跳出的循環層級。默認情況下,n為1,表明跳出的是當前的循環。如果你将n設為2,break命令就會停止下一級的外部循環。
13.7.2 continue命令
continue命令可以提前中止某次循環中的命令,但并不會完全終止整個循環。可以在循環内部設置shell不執行命令的條件。
和break命令一樣,continue命令也允許通過命令行參數指定要繼續執行哪一級循環:
continue n
其中n定義了要繼續的循環層級。
13.8 處理循環的輸出
在shell腳本中,可以對循環的輸出使用管道或進行重定向。這可以通過在done命令之後添加一個處理命令來實現。
下面将for命令的輸出重定向到文件,而不是顯示在屏幕上。
這種方法同樣适用于将循環的結果管接給另一個命令。
state值并沒有在for命令列表中以特定次序列出。for命令的輸出傳給了sort命令,該命令會改變for命令輸出結果的順序。運行這個腳本實際上說明了結果已經在腳本内部排好序了。
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!