実践編:制御構文と条件分岐・繰り返し
条件判定を行うテスト構文([[ ... ]])、if や case による条件分岐、および for や while を用いた繰り返し処理の設計方法を解説します。
テスト構文(条件判定)
Bash では条件を判定する際に角括弧を使用します。従来の POSIX 標準である [ ... ](test コマンド)に加え、Bash 拡張の [[ ... ]] が利用可能です。
[[ ... ]] は単語分割やワイルドカードの不要な展開を防ぎ、正規表現もサポートするため、Bash スクリプトでは基本的に [[ ... ]] の使用が推奨されます。
» 文字列と数値の比較
Bash では文字列比較と数値比較で異なる演算子を使用します。
| 判定対象 | 演算子 | 例 |
|---|---|---|
| 文字列が一致 | == | [[ "$name" == "Alice" ]] |
| 文字列が不一致 | != | [[ "$name" != "Bob" ]] |
| 空文字列(長さ0) | -z | [[ -z "$input" ]] |
| 非空文字列 | -n | [[ -n "$input" ]] |
| 数値が等しい | -eq | [[ "$count" -eq 10 ]] |
| 数値が大きい | -gt | [[ "$size" -gt 100 ]] |
| 数値が小さい | -lt | [[ "$age" -lt 20 ]] |
» ファイルとディレクトリの判定
ファイルシステムの検証で頻出する主要なテスト演算子です。
# 通常ファイルが存在するか確認
if [[ -f "/etc/hosts" ]]; then
echo "hosts file exists."
fi
# ディレクトリが存在するか確認
if [[ -d "./build" ]]; then
echo "build dir exists."
fi
# 実行権限があるか確認
if [[ -x "./deploy.sh" ]]; then
echo "deploy.sh is executable."
fi
» 正規表現マッチング(=~)
=~ 演算子を用いて、入力値が正規表現パターンに合致するかを判定できます。マッチした部分は組み込み配列変数 BASH_REMATCH に格納されます。
INPUT="port:8080"
if [[ "$INPUT" =~ ^port:([0-9]+)$ ]]; then
PORT_NUM="${BASH_REMATCH[1]}"
echo "Matched port: $PORT_NUM"
fi
条件分岐(if と case)
状況に応じて異なる処理を実行するための構文です。
» if / elif / else / fi
STATUS=200
if [[ "$STATUS" -eq 200 ]]; then
echo "Success: OK"
elif [[ "$STATUS" -eq 404 ]]; then
echo "Error: Not Found"
else
echo "Unexpected status code: $STATUS"
fi
» case / in / esac
コマンドライン引数の処理や、特定パターンの分類には case 文が適しています。各パターンの終端にはセミコロンを2つ(;;)記述します。
ACTION="$1"
case "$ACTION" in
start)
echo "Starting service..."
;;
stop)
echo "Stopping service..."
;;
restart|reload)
echo "Restarting service..."
;;
*)
echo "Usage: $0 {start|stop|restart}" >&2
exit 1
;;
esac
繰り返し構文(for と while)
連続したデータやファイルを順次処理するループ構文です。
» for ループ
配列の要素やワイルドカードで展開されたファイル一覧を走査します。
# 配列の全要素をループ
REGIONS=("ap-northeast-1" "us-west-2" "eu-west-1")
for region in "${REGIONS[@]}"; do
echo "Checking region: $region"
done
# C 言語スタイルの数値ループ
for ((i = 1; i <= 5; i++)); do
echo "Step: $i"
done
» while ループとファイルの1行読み込み
条件が真である間、処理を繰り返します。ファイルを1行ずつ安全に読み込む定石パターンとして read -r との組み合わせが使われます。
# ファイルから1行ずつ読み込んで処理
while IFS= read -r line; do
echo "Processing: $line"
done < "./data.txt"
-r オプションはバックスラッシュのエスケープ解釈を無効化し、IFS= は前後の不要な空白トリムを防止します。