在這關於流程控制的最後一章中,我們將看看另一種 shell 迴圈構造。for 迴圈不同於 while 和 until 迴圈,因為 在迴圈中,它提供了一種處理序列的方式。這證明在程式設計時非常有用。因此在 bash 指令碼中,for 迴圈是非常流行的構造。
實現乙個 for 迴圈,很自然的,要用 for 命令。在現代版的 bash 中,有兩種可用的 for 迴圈格式。
原來的 for 命令語法是:
這裡的 variable 是乙個變數的名字,這個變數在迴圈執行期間會增加,words 是乙個可選的條目列表, 其值會按順序賦值給 variable,commands 是在每次迴圈迭代中要執行的命令。for variable [in words]; do
commands
done
在命令列中 for 命令是很有用的。我們可以很容易的說明它是如何工作的:
在這個例子中,for 迴圈有乙個四個單詞的列表:「a」,「b」,「c」,和 「d」。由於這四個單詞的列表,for 迴圈會執行四次。 每次迴圈執行的時候,就會有乙個單詞賦值給變數 i。在迴圈體內,我們有乙個 echo 命令會顯示 i 變數的值,來演示賦值結果。 正如 while 和 until 迴圈,done 關鍵字會關閉迴圈。[me@linuxbox ~]$ for i in a b c d; do echo $i; doneab
cd
for 命令真正強大的功能是我們可以通過許多有趣的方式建立 words 列表。例如,通過花括號展開:
或者路徑名展開:[me@linuxbox ~]$ for i in ; do echo $i; doneab
cd
或者命令替換:[me@linuxbox ~]$ for i in distros*.txt; do echo $i; done
distros-by-date.txt
distros-dates.txt
distros-key-names.txt
distros-key-vernums.txt
distros-names.txt
distros.txt
distros-vernums.txt
distros-versions.txt
在這個示例中,我們要在乙個檔案中查詢最長的字串。當在命令列中給出乙個或多個檔名的時候, 該程式會使用 strings 程式(其包含在 gnu binutils 包中),為每乙個檔案產生乙個可讀的文字格式的 「words」 列表。 然後這個 for 迴圈依次處理每個單詞,判斷當前這個單詞是否為目前為止找到的最長的乙個。當迴圈結束的時候,顯示出最長的單詞。#!/bin/bash
# longest-word : find longest string in a file
while [[ -n $1 ]]; do
if [[ -r $1 ]]; then
max_word=
max_len=0
for i in $(strings $1); do
len=$(echo $i | wc -c)
if (( len > max_len )); then
max_len=$len
max_word=$i
fidone
echo "$1: '$max_word' ($max_len characters)"
fishift
done
如果省略掉 for 命令的可選項 words 部分,for 命令會預設處理位置引數。 我們將修改 longest-word 指令碼,來使用這種方式:
正如我們所看到的,我們已經更改了最外圍的迴圈,用 for 迴圈來代替 while 迴圈。通過省略 for 命令的 words 列表, 用位置引數替而代之。在迴圈體內,之前的變數 i 已經改為變數 j。同時 shift 命令也被淘汰掉了。#!/bin/bash
# longest-word2 : find longest string in a file
for i; do
if [[ -r $i ]]; then
max_word=
max_len=0
for j in $(strings $i); do
len=$(echo $j | wc -c)
if (( len > max_len )); then
max_len=$len
max_word=$j
fidone
echo "$i: '$max_word' ($max_len characters)"
fidone
為什麼是 i?最新版本的 bash 已經新增了第二種格式的 for 命令語法,該語法相似於 c 語言中的 for 語法格式。 其它許多程式語言也支援這種格式:你可能已經注意到上面所列舉的 for 迴圈的例項都選擇 i 作為變數。為什麼呢? 實際上沒有具體原因,除了傳統習慣。 for 迴圈使用的變數可以是任意有效的變數,但是 i 是最常用的乙個,其次是 j 和 k。
這一傳統的基礎源於 fortran 程式語言。在 fortran 語言中,以字母 i,j,k,l 和 m 開頭的未宣告變數的型別 自動設為整形,而以其它字母開頭的變數則為實數型別(帶有小數的數字)。這種行為導致程式設計師使用變數 i,j,和 k 作為迴圈變數, 因為當需要乙個臨時變數(正如迴圈變數)的時候,使用它們工作量比較少。這也引出了如下基於 fortran 的俏皮話:
「神是真實的,除非是宣告的整數。」
這裡的 expression1,expression2,和 expression3 都是算術表示式,commands 是每次迴圈迭代時要執行的命令。 在行為方面,這相當於以下構造形式:for (( expression1; expression2; expression3 )); do
commands
done
expression1 用來初始化迴圈條件,expression2 用來決定迴圈結束的時間,還有在每次迴圈迭代的末尾會執行 expression3。(( expression1 ))
while (( expression2 )); do
commands
(( expression3 ))
done
這裡是乙個典型應用:
指令碼執行之後,產生如下輸出:#!/bin/bash
# ******_counter : demo of c style for command
for (( i=0; i<5; i=i+1 )); do
echo $i
done
在這個示例中,expression1 初始化變數 i 的值為0,expression2 允許迴圈繼續執行只要變數 i 的值小於5, 還有每次迴圈迭代時,expression3 會把變數 i 的值加1。[me@linuxbox ~]$ ******_counter01
234
c 語言格式的 for 迴圈對於需要乙個數字序列的情況是很有用處的。我們將在接下來的兩章中看到幾個這樣的應用例項。
學習了 for 命令的知識,現在我們將對我們的 sys_info_page 指令碼做最後的改進。 目前,這個 report_home_space 函式看起來像這樣:
report_home_space ()
report_home_space ()
這次重寫應用了目前為止我們學過的許多知識。我們仍然測試超級使用者(superuser),但是我們在 if 語句塊內 設定了一些隨後會在 for 迴圈中用到的變數,來取代在 if 語句塊內執行完備的動作集合。我們新增了給 函式新增了幾個本地變數,並且使用 printf 來格式化輸出。
流程控制(迴圈)
1.塊語句 成為乙個整體 語句1 語句2 語句 空語句 非空語句 2.程式的流程控制 順序,選擇控制,迴圈 1.迴圈執行 從上往下,逐條來執行 2.選擇控制 當達到某種條件,執行特定的指令。if switch if 邏輯條件表示式 語句 雙分支 if 表示式 條件為真 語句1 else 條件為假 語...
流程控制 迴圈
迴圈就是重複執行一些語句。這個技術使用起來非常方便,因為可以對操作重複任意多次,而無需每次都要編寫相同的 例如,下面的 計算乙個銀行賬戶在10年後的金額,假定不計算每天的利息,且該賬戶沒有其他款項的訪問 double balance 1000 double interestrate 1.05 5 i...
流程控制 跳出迴圈
在迴圈過程中,有時候需要在未達到迴圈結束條件時強制跳出迴圈,像大多數程式語言一樣,shell也使用 break 和 continue 來跳出迴圈。break命令允許跳出所有迴圈 終止執行後面的所有迴圈 下面的例子中,指令碼進入死迴圈直至使用者輸入數字大於5。要跳出這個迴圈,返回到shell提示符下,...