【Shell Script】case文で複数条件をすっきり書く

Shell Script

こんにちは、かつコーチです。

「if・elifが何段も連なって、どこで何を判定しているのか読みにくい」。
1つの変数の値によって処理を分けるスクリプトを書いていると、そんな悩みにぶつかります。
この記事では、複数の条件分岐をすっきり書けるcase文の使い方を、if文(04-if-bun-joken-bunki)との比較を交えて解説します。
デプロイスクリプトの環境切り替えなど、実務でよく登場するパターンです。

case文とは?

1つの値を複数のパターンで振り分ける仕組み

case文とは、1つの変数の値を複数のパターン(条件)と順番に比較し、一致したパターンの処理だけを実行する制御構文です。

イメージとしては、郵便局の仕分け機に近いものです。
仕分け機は荷物の宛先(1つの値)を見て、対応する配送ルートの棚に振り分けていきます。
if・elifで1つずつ条件を書いていく代わりに、case文は「この値ならこの処理」という対応表をまとめて書けるのが特徴です。

なぜcase文が必要なのか

if・elifでも同じ分岐は書けますが、比較対象がすべて同じ変数の場合、elifを重ねるほど条件式が繰り返し登場して読みにくくなります。
case文を使うと、比較対象の変数を1回書くだけで済み、パターンと処理の対応が一覧しやすくなります。
「1つの値によって処理を振り分ける」場面では、if・elifよりcase文の方が可読性が高くなるのがポイントです。

基本の書き方

case文の基本構文

case文はcase 値 inから始まり、パターン) 処理 ;;を並べ、esacで閉じます。

#!/bin/bash

env="production"

case "$env" in
  development)
    echo "開発環境として起動します"
    ;;
  staging)
    echo "ステージング環境として起動します"
    ;;
  production)
    echo "本番環境として起動します"
    ;;
  *)
    echo "不明な環境です: $env"
    ;;
esac

*)はどのパターンにも一致しなかった場合の受け皿で、if文のelseにあたります。
各処理の末尾には;;を書き、そこで1つのパターンの処理が終わったことを示します。

複数パターンをまとめて指定する

|(パイプ)で区切ると、複数のパターンを1つの処理にまとめられます。

#!/bin/bash

read -p "拡張子を入力してください: " ext

case "$ext" in
  jpg|jpeg|png|gif)
    echo "画像ファイルです"
    ;;
  txt|md|csv)
    echo "テキストファイルです"
    ;;
  *)
    echo "対応していない拡張子です"
    ;;
esac

コマンドライン引数の分岐に使う

case文は、スクリプトの引数によって動作を切り替える用途でもよく使われます。

#!/bin/bash

case "$1" in
  start)
    echo "サービスを起動します"
    ;;
  stop)
    echo "サービスを停止します"
    ;;
  restart)
    echo "サービスを再起動します"
    ;;
  *)
    echo "使い方: $0 {start|stop|restart}"
    exit 1
    ;;
esac

よくあるつまずきポイント・エラー対処

;;を書き忘れて構文エラーになる

case文を書き始めたばかりのころ、パターンごとの処理の締めを忘れてこんなエラーに遭遇しました。

❌Before(つまずいた実例)

#!/bin/bash

case "$1" in
  start)
    echo "起動します"
  stop)
    echo "停止します"
    ;;
esac

実行すると、次のような構文エラーが出ました。

script.sh: line 6: syntax error near unexpected token `stop'

✅After(解決方法)

原因は、start)の処理の末尾に;;を書いていなかったことです。
;;がないと、シェルは次の行もまだ同じパターンの処理だと解釈しようとして構文が崩れます。
すべてのパターンの末尾に;;を付けるよう見直したところ、正常に動くようになりました。

#!/bin/bash

case "$1" in
  start)
    echo "起動します"
    ;;
  stop)
    echo "停止します"
    ;;
esac

「パターンの処理は必ず;;で終える」というルールを忘れると、離れた行でエラーが出てわかりにくいので注意してください。

応用・一歩先の使い方

if・elifとcase文の使い分け

if・elifとcase文は、どちらも条件分岐ですが得意な場面が異なります。

判断軸if・elifcase文
比較対象複数の異なる変数・条件式でもOK1つの値をパターンと比較する場合に向く
数値の範囲判定(〜以上、〜未満)得意苦手(パターンマッチ中心)
文字列・拡張子の分岐書けるが冗長になりやすい得意、可読性が高い
判定パターンが多い(4つ以上)elifが増えて読みにくくなりがちパターンが増えても見通しがよい

「複数の値のどれに一致するか」を判定するならcase文、「数値の大小」や「複数条件のAND・OR」を判定するならif文、という使い分けが基本方針です。

ワイルドカードでパターンを柔軟にする

case文のパターンにはワイルドカード(*?)も使えます。

#!/bin/bash

filename="report-2026.csv"

case "$filename" in
  report-*.csv)
    echo "レポートファイルです"
    ;;
  *.log)
    echo "ログファイルです"
    ;;
esac

report-*.csvのように前方一致・部分一致のパターンを組めるので、ファイル名の命名規則に沿った振り分けに便利です。

まとめ

この記事のポイント

  • case文は1つの値を複数パターンと比較し、一致した処理だけを実行する
  • パターンの処理は必ず;;で終える。忘れると構文エラーになる
  • *)はif文のelseにあたる受け皿パターン
  • 1つの値による分岐が多いときはcase文、数値範囲や複雑な条件はif・elifが向いている

次に読むべき記事

条件分岐の次は、スクリプトの外から値を受け取る「コマンドライン引数の受け取り方(1・@・$#)」を読んでみてください。

タグ: Shell, 中級者向け, 制御構文

タイトルとURLをコピーしました