Bashのfor文の書き方: ループ文で繰り返し処理を行う
- 作成日: 2020-08-21
- 更新日: 2023-12-24
- カテゴリ: Bash
Bashのfor文の書き方
Bashではfor
文を使うことが出来ます。
for
文は初期化、判定、更新を使った普通のfor
文と、in
を使った配列などを回すのに適したfor
文があります。
Bashのfor
文は↓のように書きます。
arr=(1 2 3)
for ((i=0; i<${#arr[@]}; i++)); do
echo ${arr[$i]}
done
# または
for el in "${arr[@]}"; do
echo $el
done
普通のfor文
Bashでよく使われる普通のfor
文は↓のフォーマットで書きます。
for ((初期化; 判定; 更新)); do
処理
done
for
文は↓の流れに沿って実行されます。
- 初期化
- 判定
- 処理
- 更新
- 2 に戻る
たとえばカウント変数i
を4
より下までカウントし、echo
するコードは↓のようになります。
for ((i=0; i<4; i++)); do
echo $i
done
# 0
# 1
# 2
# 3
↑のコードの場合、まず「初期化」のi=0
が実行されます。
その次に「判定」のi<4
が実行され、次に「処理」のecho $i
が実行されます。
そして「更新」のi++
が実行され、再び「判定」のi<4
に戻ります。
「処理」部分では複数行のコードを書くことが出来ます。
inを使ったfor文
in
を使ったfor
文は配列などを順に走査するのに適しています。
for 変数名 in ${配列名[@]}; do
処理
done
このfor
文は配列の先頭から順に要素にアクセスします。
要素は「変数名」に渡されて、それに対してアクセスすることになります。
たとえば値1
, 2
, 3
が格納された配列をこのfor
文で回す場合は↓のようになります。
arr=(1 2 3)
for el in ${arr[@]}; do
echo $el
done
# 1
# 2
# 3
${arr[@]}
に注目してください。ここで配列の全要素に対してアクセスしています。
ここをダブルクオートで囲むかどうかで要素の走査方法が変わるので注意してください。
たとえば文字列を含んだ配列があって、その文字列がスペースを含んでいるとします。
そうすると、for
文でダブルクオートで囲まない場合は、そのスペースがチョップされます。
arr=("The cat" "The dog")
for el in ${arr[@]}; do
echo $el
done
# The
# cat
# The
# dog
一方、for
文でダブルクオートで囲む、つまり"${arr[@]}"
にした場合は、スペースはチョップされません。
arr=("The cat" "The dog")
for el in "${arr[@]}"; do
echo $el
done
# The cat
# The dog
ここら辺はBashのfor
文のはまりやすいところなので覚えておくと良いと思います。
特に意図が無い限りはダブルクオートで囲むようにしたほうが良いでしょう。
for文のbreak文
for
文のループから脱出したい場合はbreak
を使います。
for ((i=0; i<4; i++)); do
break
done
echo $i
# 0
↑の場合、for
文の処理の冒頭でbreak
しているので、ループに入った直後にfor
文から脱出しています。
よってecho $i
の結果は0
になります。これは、ループがカウント0
の段階で終了したことを表しています。
break
文はif
文の中でも機能します。
for ((i=0; i<4; i++)); do
if [ $i == 2 ]; then
break
fi
done
echo $i
# 2
↑の場合、カウント変数が2
になったらif
文が真になり、break
によってfor
文から脱出します。
for
文が入れ子になっている場合、break
は最も近い外側のfor
文に対してのみ作用します。
for ((i=0; i<4; i++)); do
for ((j=0; j<4; j++)); do
break
done
done
echo $i
# 4
echo $j
# 0
↑のbreak
文はカウント変数j
を使用しているfor
文に対してのみ作用します。
カウント変数i
を使用しているfor
文に作用するbreak
は↓のように書きます。
for ((i=0; i<4; i++)); do
break
for ((j=0; j<4; j++)); do
echo $j
done
done
echo $i
# 0
↑のbreak
はカウント変数j
を使用しているfor
文には作用しません。
for文のcontinue文
for
文のループをスキップしたい場合はcontinue
文を使います。
for ((i=0; i<4; i++)); do
echo $i
continue
echo "Come on!"
done
# 0
# 1
# 2
# 3
↑の場合、continue
文が実行された時点でそれ以降の処理はスキップされます。
つまりecho "Come on!"
は実行されません。
continue
文もif
文の中で使うことが出来ます。
for ((i=0; i<4; i++)); do
if [ $i -ge 2 ]; then
continue
fi
echo $i
done
# 0
# 1
continue
文ももっとも近い外側のfor
文に対してのみ作用します。
for ((i=0; i<4; i++)); do
echo i $i
for ((j=0; j<4; j++)); do
continue
echo j $j
done
done
# i 0
# i 1
# i 2
# i 3
↑の場合、echo j $j
は実行されません。
Bashのfor文の使用例
Bashのfor
文の使用例です。
1~100までの総和を計算する
$(())
は算術式展開です。
ちなみにこれはfor
文を使わなくても有名な公式を使えば一発で計算可能です。
sum=0
for ((i=1; i<=100; i++)); do
sum=$(( $sum + $i ))
done
echo $sum
# 5050
空じゃないファイルを羅列する
ls
の出力をfor
文で回し、ファイルが空じゃなければ表示します。
for fname in `ls`; do
if [ -s "$fname" ]; then
echo $fname
fi
done
0~255のホストにpingを1回送る
指定のネットワークの各ホストにping
を1回だけ送ります。
host="192.168.11."
for ((i=0; i<=255; i++)); do
ip="$host$i"
ping -c 1 "$ip"
done
問題
Q1: 普通のfor
文で、初期化の後に呼ばれるのはなにか答えよ。
- 更新
- 処理
- 判定
Q2: in
を使ったfor
文はどんな時に適しているか答えよ。
- 配列を順に走査したいとき
- lsの出力を回すとき
- カウント変数をカウントしたいとき
Q3: break
の作用として正しいものを答えよ。
- もっとも内側のfor文に対して作用する
- もっとも外側のfor文に対して作用する
- もっとも近い外側のfor文に対して作用する
答え
Q1: 3
Q2: 1, 2
Q3: 3