Bash 有兩種迴圈形式:
for迴圈若要疊代一串項目,我們會使用for迴圈。
for varname in words; do COMMANDS; done
words會透過單字分割與檔名展開來展開(我們在引號概念中學過)。
每個單字會依序被指定給varname,然後執行 COMMANDS。
以下是一些範例,說明for迴圈在什麼時候很有用:
對一群檔案執行某些指令。
# source all the bash library files in the current directory
for file in ./*.bash; do
source "$file"
done
對指令碼或函式的每個參數執行某些指令。
for arg in "$@"; do
echo "argument: ${arg}"
done
對某個指令輸出中每個以空白分隔的單字執行某些指令。
for i in $(seq 10); do
echo "${i} squared is $((i * i))"
done
我們之後會看到一些關於這種寫法的警告。
for迴圈Bash 確實有算術迴圈。 這對學過其他程式語言的人來說會有點熟悉。
for ((INITIALIZATION; CONDITION; INCREMENT)); do COMMANDS; done
bash 中的雙重小括號代表算術情境(我們會在之後的概念中看到更多關於 bash 算術的內容)。
上面使用seq的範例可以寫成這樣
for ((i = 1; i <= 10; i++)); do
echo "${i} squared is $((i * i))"
done
for
這是你經常會看到的反面模式:對cat的輸出進行疊代。
for line in $(cat some.file); do
do_something_with "$line"
done
這麼做有兩個錯誤。
for迴圈疊代的是檔案中的單字,而不是行。如同我們在引號概念中學到的,單字分割可以用IFS變數控制,檔名展開也可以關閉。
但這往往是脆弱的做法。
for不是疊代檔案各行的正確方法。
讀取檔案的慣用做法是使用while迴圈。
while迴圈使用while在_某個條件為 true 時_重複執行一連串指令。
while CONDITION_COMMANDS; do COMMANDS; done
就像if一樣,CONDITION_COMMANDS 並沒有特殊的語法(我們在條件判斷概念中學過)。
指令清單的結束狀態會決定是 true 還是 false。
break指令會跳出迴圈。
控制權會從迴圈done結束符號之後的指令繼續。
continue指令會跳到迴圈的下一次疊代。
如前所述,while迴圈是讀取檔案的慣用做法。
while IFS= read -r line; do
do_something_with "$line"
done < some.file
檔案的內容透過<重導向作為迴圈的輸入。
read指令若能從輸入讀取完整的一行,就會回傳 true。
當輸入被讀完,或最後一行結尾沒有換行符號時,read 會回傳 false。
讀取檔案各行_真正_慣用的做法,即使最後一行結尾沒有換行符號也可以,是
while IFS= read -r line || [[ -n "$line" ]]; do ...
-r選項會告訴read不要替換反斜線序列:反斜線就只是一般的字元。
IFS=只在read指令執行期間把空字串指定給 IFS。
這會暫時關閉單字分割,讓傳入的那一行文字中開頭或結尾的空白都能保留下來。
untiluntil結構會在某個條件為false時重複執行一連串指令。
迴圈會重複,_直到_條件變成 true 為止。
until CONDITION_COMMANDS; do COMMANDS; done
很少會用到until。
更常見的是使用「while not」迴圈。
while ! CONDITION_COMANDS; do ...
有時你會想讓迴圈永遠執行下去。 這裡有兩種做法喔。
條件永遠是成功結束狀態的while迴圈
while true; do ...
運算式留空的算術for迴圈
for ((;;)); do ...
沒有明確的 do-while 結構,但你可以達到相同的效果:
while true; do
COMMANDS
if END_CONDITION; then
break
fi
done