本記事では、bashでのcase文の使い方を解説します。
case文とは
case文は、bashにおける条件分岐のための構文の一つです。複数の条件に対して異なる処理を行いたい場合、ifとelifの連続よりも可読性が高く、保守しやすいコードを書くことができます。特に、一つの変数や式に対して複数のパターンマッチングを行いたい場合に適しています。
構文
bashにおけるcase文の基本構文は以下のとおりです。
case 変数 in
パターン1)
コマンド1
;;
パターン2)
コマンド2
;;
パターン3)
コマンド3
;;
*)
デフォルトのコマンド
;;
esac
各パターンの後には、実行したいコマンドを記述し、;;でパターンの終わりを示します。最後の*)は、どのパターンにもマッチしなかった場合のデフォルト処理を定義します。
例
基本的な例
以下の例では、ユーザーが選択したメニュー番号に応じて異なるコマンドを実行します。1を選ぶと日時表示、2を選ぶとファイル一覧表示、3を選ぶとユーザー名表示、qを選ぶと終了、それ以外の入力は無効として扱われます。
#!/bin/bash
echo "メニューを選択してください: "
echo "1: 現在の日時を表示"
echo "2: 現在のディレクトリのファイル一覧を表示"
echo "3: 現在のユーザー名を表示"
echo "q: 終了"
read choice
case $choice in
1)
date
;;
2)
ls -la
;;
3)
whoami
;;
q|Q)
echo "プログラムを終了します"
exit 0
;;
*)
echo "無効な選択です"
;;
esac
実行結果
メニューを選択してください:
1: 現在の日時を表示
2: 現在のディレクトリのファイル一覧を表示
3: 現在のユーザー名を表示
q: 終了
1 # 1を入力
2025年 3月14日 金曜日 18時36分03秒 JST
パターンマッチングの例
この例では、ユーザーが入力した果物の名前に応じて、その果物の色を表示します。「りんご」「バナナ」「オレンジ/みかん」のいずれかを入力すると、対応する色が表示され、それ以外の果物名の場合は「色が分からない」と表示されます。「オレンジ」と「みかん」は同じパターンとして扱われています。
#!/bin/bash
echo "果物の名前を入力してください: "
read fruit
case $fruit in
"りんご")
echo "りんごは赤いです"
;;
"バナナ")
echo "バナナは黄色いです"
;;
"オレンジ"|"みかん")
echo "オレンジ/みかんはオレンジ色です"
;;
*)
echo "その果物の色は分かりません"
;;
esac
実行結果
果物の名前を入力してください:
りんご # りんごを入力
りんごは赤いです
注意点
パターンの順序
パターンは上から順に評価されるため、具体的なパターンを先に、一般的なパターンを後に配置しましょう。
#!/bin/bash
echo "数字を入力してください: "
read number
case $number in
# 具体的なパターンを先に評価
1)
echo "入力値は1です"
;;
# より一般的なパターンを後に評価
[0-9])
echo "入力値は1桁の数字です"
;;
*)
echo "入力値は1桁の数字ではありません"
;;
esac
この例では、「1」という具体的なパターンを先に評価し、その後で「任意の1桁の数字」という一般的なパターンを評価しています。もし順序を逆にすると、「1」が入力された場合でも常に「入力値は1桁の数字です」と表示されてしまい、「入力値は1です」という分岐に到達しなくなります。
終了記号
各パターンブロックの終わりには必ず;;を付けてください。bash 4.0以降では;;&や;&も使えますが、これらは特殊な動作をします。
#!/bin/bash
echo "数値を入力してください: "
read num
case $num in
# 標準的な終了記号 ;;
1)
echo "値は1です"
;;
# フォールスルー機能を持つ ;& (次のパターンも実行)
2)
echo "値は2です"
;&
3)
echo "値は2または3です"
;;
# 再評価機能を持つ ;;& (次のパターンを評価)
4)
echo "値は4です"
;;&
[4-6])
echo "値は4から6の間です"
;;
*)
echo "その他の値です"
;;
esac
この例では、2を入力すると「値は2です」と「値は2または3です」の両方が表示されます(;&でフォールスルー)。4を入力すると「値は4です」と「値は4から6の間です」の両方が表示されます(;;&で再評価)。
複数パターン
|を使って複数のパターンを指定できます。
#!/bin/bash
echo "曜日を入力してください(例: 月): "
read day
case $day in
"月"|"水"|"金")
echo "ゴミ収集日です"
;;
"火"|"木")
echo "資源ごみの日です"
;;
"土"|"日")
echo "収集はありません"
;;
*)
echo "無効な入力です"
;;
esac
この例では、「月」「水」「金」のいずれかが入力された場合に「ゴミ収集日です」と表示されます。複数のパターンを|で区切ることで、同じ処理を適用するパターンをまとめて記述できます。
大文字・小文字の区別
bashは基本的に大文字・小文字を区別します。大文字・小文字を区別せずにマッチングしたい場合は、明示的に両方のパターンを記述するか、shopt -s nocasematchを使用します。
#!/bin/bash
# 大文字小文字を区別しない設定
shopt -s nocasematch
echo "「はい」または「いいえ」と入力してください: "
read answer
case $answer in
"はい"|"yes"|"y")
echo "処理を続行します"
;;
"いいえ"|"no"|"n")
echo "処理を中止します"
;;
*)
echo "無効な回答です"
;;
esac
# 設定を元に戻す
shopt -u nocasematch
この例では、shopt -s nocasematchを使用することで、「yes」と入力しても「YES」と入力しても同じように「処理を続行します」と表示されます。スクリプトの最後でshopt -u nocasematchを実行して設定を元に戻しています。
グロビング
case文ではパターンマッチングにワイルドカード(*, ?, [])が使えます。これらはファイル名のグロビングと同じ規則に従います。
#!/bin/bash
echo "メールアドレスを入力してください: "
read email
case $email in
*@gmail.com)
echo "Gmailアドレスです"
;;
*@yahoo.*)
echo "Yahooのアドレスです"
;;
*@*.co.jp)
echo "日本の企業ドメインです"
;;
[a-zA-Z0-9._%+-]*@*.[a-zA-Z]{2,})
echo "有効なメールアドレスの形式です"
;;
*)
echo "認識できないメールアドレス形式です"
;;
esac
この例では、入力されたメールアドレスのパターンに応じて異なるメッセージを表示します。*(任意の文字列)、[](文字クラス)などのワイルドカードを使用して柔軟なパターンマッチングを実現しています。
まとめ
bashのcase文は、多岐にわたる条件分岐を簡潔に記述できる強力な構文です。ifとelifの連続よりも読みやすく、特に一つの変数に対して複数のパターンマッチングを行う場合に威力を発揮します。基本構文を理解し、パターンマッチングの特性を活用すれば、より効率的で保守しやすいシェルスクリプトを作成できるでしょう。
実際のシェルスクリプト開発では、条件の複雑さや読みやすさを考慮して、if文とcase文を適切に使い分けることが重要です。シンプルな条件分岐ならif文、複数のパターンマッチングが必要な場合はcase文を選択するとよいでしょう。