Bashには3つの異なるループ構文(for、while、until)があり、それぞれ特定の状況で最適に機能します。本記事では各ループ構文の基本的な使い方から実践的な例、そして適切な使い分けまでを解説します。これらの知識を身につけることで、ファイル処理、データ加工、システム監視など様々な自動化タスクを実現するシェルスクリプトを作成できるようになります。
ループ処理の方法
Bashには主に以下の3つのループ構文があります。
- forループ
- whileループ
- untilループ
ここではそれぞれのループの基本的な使い方と具体例を紹介します。
forループ
構文
forループは指定したリストの要素を順番に処理する構文です。リストにはスペース区切りの値を直接書くことができ、{1..10}のような連番やコマンド置換なども使えます。
for 変数 in リスト
do
コマンド ...
done
例 1: 単純にリストを回す
配列を定義し、その要素を順番に処理する基本的なforループの例です。配列の全要素に対して処理を行います。
#!/bin/bash
colors=(red green blue) # 配列を定義
for color in "${colors[@]}" # 配列の全要素をループ
do
echo "color: $color"
done
# 出力:
# color: red
# color: green
# color: blue
例 2: 連番を利用する
中括弧{}を使って連番を生成し、それをforループで処理する例です。1から5までの数値を順番に出力します。
#!/bin/bash
# {}を使った連番
for i in {1..5}
do
echo "Number: $i"
done
# 出力:
# Number: 1
# Number: 2
# Number: 3
# Number: 4
# Number: 5
例 3: 数値範囲を指定するfor
C言語スタイルのforループ構文です。二重括弧(( ))の中で初期化・条件・増分を指定できます。0から4までの数値を出力します。
#!/bin/bash
for ((i=0; i<5; i++))
do
echo "i: $i"
done
# 出力:
# i: 0
# i: 1
# i: 2
# i: 3
# i: 4
whileループ
構文
whileループは条件式が真(0)の間、処理を繰り返し実行する構文です。条件式が偽(0以外)になるとループを終了します。
while [ 条件式 ]
do
コマンド ...
done
whileについては以下で詳しく説明しているので参照ください。
例 1: カウンタを使ったwhileループ
カウンタ変数を使ったwhileループの例です。カウンタが5以下の間、ループを続け、各ステップでカウンタをインクリメントします。
#!/bin/bash
count=1
while [ $count -le 5 ]
do
echo "count = $count"
count=$((count + 1)) # カウンタをインクリメント
done
# 出力:
# count = 1
# count = 2
# count = 3
# count = 4
# count = 5
例 2: ファイルを行ごとに読み込むwhileループ
ファイルの内容を1行ずつ読み込んで処理するwhileループの例です。done < ファイル名の形式でファイルをストリームとして読み込みます。
#!/bin/bash
# "lines.txt" を一行ずつ読み込んで処理
while read line
do
echo "Line: $line"
done < lines.txt
# 出力:
# Line: (lines.txtの1行目)
# Line: (lines.txtの2行目)
# ...
シェルスクリプトの内部だけでなく、パイプと組み合わせて使うこともできます。
cat lines.txt | while read line; do echo "Line: $line"; done
# 出力:
# Line: (lines.txtの1行目)
# Line: (lines.txtの2行目)
# ...
例 3: メニュー選択のwhileループ
ユーザーが有効なオプションを選択するまでメニューを表示し続けるwhileループの例です。対話型スクリプトでよく使われるパターンです。
#!/bin/bash
# 初期選択をクリア
selection=""
# 有効な選択がされるまでループ
while [ "$selection" != "1" ] && [ "$selection" != "2" ] && [ "$selection" != "q" ]
do
clear # 画面をクリア
echo "メニューを選択してください:"
echo "1) オプション1を実行"
echo "2) オプション2を実行"
echo "q) 終了"
read -p "選択 (1, 2, q): " selection
case $selection in
1)
echo "オプション1が選択されました"
sleep 2
;;
2)
echo "オプション2が選択されました"
sleep 2
;;
q)
echo "プログラムを終了します"
;;
*)
echo "無効な選択です。もう一度お試しください"
sleep 2
selection=""
;;
esac
done
# 出力:
# メニューを選択してください:
# 1) オプション1を実行
# 2) オプション2を実行
# q) 終了
# 選択 (1, 2, q): 3
# 無効な選択です。もう一度お試しください
# (メニューが再表示される)
# 選択 (1, 2, q): 1
# オプション1が選択されました
untilループ
構文
untilループはwhileループの逆で、条件式が偽(0以外)の間ループを実行し、条件式が真(0)になるとループを終了します。
until [ 条件式 ]
do
コマンド ...
done
例 1: untilの基本的な使い方
untilループの基本的な使用例です。カウントが5より大きくなるまでループを続けます。
#!/bin/bash
count=1
until [ $count -gt 5 ]
do
echo "count = $count"
count=$((count + 1))
done
# 出力:
# count = 1
# count = 2
# count = 3
# count = 4
# count = 5
例 2: ファイルが存在するまで待機する
特定のファイルが作成されるまで待機するuntilループの例です。バックグラウンドプロセスやジョブの完了を監視する際に役立ちます。
#!/bin/bash
echo "ファイルの作成を待機しています..."
until [ -f "/tmp/job_complete.txt" ]
do
echo "まだファイルが存在しません。5秒待機します..."
sleep 5
done
echo "ファイルが作成されました。処理を続行します。"
# 出力:
# ファイルの作成を待機しています...
# まだファイルが存在しません。5秒待機します...
# まだファイルが存在しません。5秒待機します...
# ファイルが作成されました。処理を続行します。
例 3: ユーザー入力を待つ
正しい入力が得られるまでユーザーに繰り返し入力を求めるuntilループの例です。入力検証に役立ちます。
#!/bin/bash
echo "1から10までの数字を入力してください:"
until [ "$number" -ge 1 ] && [ "$number" -le 10 ] 2>/dev/null
do
read -p "数字を入力: " number
if ! [[ "$number" =~ ^[0-9]+$ ]] || [ "$number" -lt 1 ] || [ "$number" -gt 10 ]; then
echo "エラー: 1から10までの数字を入力してください。"
unset number
fi
done
echo "入力された数字は $number です。処理を続行します。"
# 出力:
# 1から10までの数字を入力してください:
# 数字を入力: abc
# エラー: 1から10までの数字を入力してください。
# 数字を入力: 15
# エラー: 1から10までの数字を入力してください。
# 数字を入力: 7
# 入力された数字は 7 です。処理を続行します。
ループ処理の使い分け
Bashの3つのループ構文(for、while、until)はそれぞれ特徴があり、状況に応じて適切に使い分けることでスクリプトの効率と可読性が向上します。ここでは各ループ構文の適切な使用場面を解説します。
forループを使うべき場面
forループは以下のような場合に最適です。
- リストの要素を順番に処理したい場合
- 一定回数の繰り返し処理を行いたい場合
- ファイル名のパターンマッチングで複数ファイルを処理したい場合
whileループを使うべき場面
whileループは以下のような場合に適しています。
- 条件が満たされる限り処理を続けたい場合
- ファイルを1行ずつ読み込んで処理したい場合
- ユーザー入力を繰り返し受け付けたい場合
- 無限ループでデーモンのように動作させたい場合
untilループを使うべき場面
untilループは以下のような場合に適しています。
- 条件が満たされるまで処理を続けたい場合(whileの否定形)
- リソースが利用可能になるまで待機したい場合
- 特定のイベントが発生するまで監視したい場合
使い分けの基準
ループ構文の選択基準をまとめると以下のようになります。
- forループ:
- 処理対象のリストが明確に決まっている
- 処理回数が事前に分かっている
- 配列やコマンド出力の各要素に対して処理を行いたい
- whileループ:
- 条件が真である限り処理を続けたい
- ファイルの読み込みやパイプ処理と組み合わせたい
- ユーザー入力を受け付けるインタラクティブな処理を行いたい
- 無限ループ(デーモン処理)を実装したい
- untilループ:
- 条件が真になるまで処理を続けたい(whileの否定形)
- 特定のイベントやリソースの状態変化を待ちたい
- 条件の記述がuntilの方が自然に読める場合
実際のスクリプト開発では、これらの基準を参考にしつつ、コードの可読性や保守性も考慮して最適なループ構文を選択することが重要です。
まとめ
Bashのループ構文は、シェルスクリプトで繰り返し処理を実装するための重要な機能です。本記事で解説した3つのループ構文の特徴と使い分けをまとめます。
- forループ:リストの要素を順番に処理したい場合や、処理回数が事前に分かっている場合に最適です。配列の処理、連番の生成、ファイルのパターンマッチングなどに使用します。
- whileループ:条件が真である限り処理を続けたい場合に適しています。ファイルの読み込み、ユーザー入力の処理、無限ループによるデーモン処理などに活用できます。
- untilループ:条件が真になるまで処理を続けたい場合(whileの否定形)に使用します。リソースの監視やイベントの待機など、特定の条件が満たされるまで処理を続ける場合に便利です。
これらのループ構文を適切に使い分けることで、より効率的で目的に合ったシェルスクリプトを作成できます。状況に応じて最適なループ構文を選択する際は、処理対象の性質(リストか条件か)、ループの終了条件(回数か状態か)、コードの可読性などを考慮しましょう。
Bashスクリプトのループ構文の特徴として、「for 変数 in リスト」でループ対象を指定したり、「while [ 条件式 ]」や「until [ 条件式 ]」で条件を判断したり、「done < ファイル名」のように外部ファイルから入力を受けたりする書き方があります。これらの特徴を理解し活用することで、様々な自動化タスクを効率的に実装できるようになります。