ユーニックス総合研究所

  • home
  • archives
  • bash-case

Bashのcase文の書き方: パターンで分岐処理

  • 作成日: 2020-08-23
  • 更新日: 2023-12-24
  • カテゴリ: Bash

Bashのcase文の書き方

Bashにはcase文があります。
これはCやJavaScriptで言うところのswitch文に近いものです。

これを使うと、if文を使うより分岐処理が簡単に書ける場合があります。

case 1 in  
    0 ) echo "match 0" ;;  
    1 ) echo "match 1" ;;  
    2 ) echo "match 2" ;;  
esac  
# match 1  

case文の構造

case文は↓のような構造を持っています。

case 値 in  
    パターン1 ) 処理 ;;  
    パターン2 ) 処理 ;;  
    ...  
    パターンn ) 処理 ;;  
esca  

caseに値を渡し、その値に応じて処理が分岐します。
値にマッチしたパターンの処理が実行され、他の分岐の処理は実行されません。

整数による分岐

caseに整数を渡し、パターンに整数を列挙すると、パターンにマッチした処理が呼ばれます。
↓の場合、caseで評価している値は1なので、1 )のケースにマッチします。

case 1 in  
    0 ) echo "match 0" ;;  
    1 ) echo "match 1" ;;  
    2 ) echo "match 2" ;;  
esac  
# match 1  

caseに渡す値は変数にすることも出来ます。

num=1  

case "$num" in  
    0 ) echo "match 0" ;;  
    1 ) echo "match 1" ;;  
    2 ) echo "match 2" ;;  
esac  
# match 1  

defaultパターン

先ほどの整数のcase文ですが、値が0~2のいずれかでなければ、どの分岐の処理も実行されません。
いずれの分岐にもマッチしない場合の処理を書きたい場合は、パターンにアスタリスク(*)を使います。

num=3  

case "$num" in  # <- numには3が入っている  
    0 ) echo "match 0" ;;  
    1 ) echo "match 1" ;;  
    2 ) echo "match 2" ;;  
    * ) echo "match *" ;;  # <- これが実行される  
esac  
# match *  

文字列による分岐

caseには文字列を指定することも出来ます。
$1はスクリプトの第1引数です)

case "$1" in  
    "cat" ) echo "match cat" ;;  
    "dog" ) echo "match dog" ;;  
    "bird" ) echo "match bird" ;;  
    * ) echo "match *" ;;  
esac  

実行結果。

$ bash sample.sh cat  
match cat  

$ bash sample.sh dog  
match dog  

$ bash sample.sh bird  
match bird  

$ bash sample.sh pig  
match *  

パターンにORを使う

caseのパターンはOR(|)で繋ぐことが出来ます。
Aのパターン、またはBのパターンのどちらかにマッチさせたい分岐を書く場合に使います。

case "$1" in  
    "cat" | "Cat" ) echo "match cat|Cat" ;;  
    "dog" | "Dog" ) echo "match dog|Dog" ;;  
    "bird" | "Bird" ) echo "match bird|Bird" ;;  
    * ) echo "match *" ;;  
esac  

実行結果。

$ bash sample.sh cat  
match cat|Cat  

$ bash sample.sh Cat  
match cat|Cat  

$ bash sample.sh dog  
match dog|Dog  

$ bash sample.sh Dog  
match dog|Dog  

$ bash sample.sh bird  
match bird|Bird  

$ bash sample.sh Bird  
match bird|Bird  

$ bash sample.sh pig  
match *  

ワイルドカードによるマッチ

Bashのcase文のパターンにはワイルドカード(*)を使うことが出来ます。
*は任意の文字列(空文字を含む)を意味します。

case "$1" in  
    # 先頭文字が'c'で始まり、任意の文字が続く文字列にマッチする  
    c* ) echo "match c*" ;;  

    # 先頭文字が'd'で始まり、任意の文字が続く文字列にマッチする  
    d* ) echo "match d*" ;;  

    # 先頭文字が'b'で始まり、任意の文字が続く文字列にマッチする  
    b* ) echo "match b*" ;;  

    # 全てにマッチする  
    * ) echo "match *" ;;  
esac  

実行結果。

$ bash sample.sh cat  
match c*  

$ bash sample.sh dog  
match d*  

$ bash sample.sh bird  
match b*  

$ bash sample.sh pig  
match *  

任意の1文字へのマッチ

パターンに?を使うと任意の1文字にマッチさせることができます。

case "$1" in  
    # 先頭文字が任意で、2文字目が'a'の文字列にマッチする  
    ?a* ) echo "match ?a*" ;;  

    # 先頭文字が任意で、2文字目が'o'の文字列にマッチする  
    ?o* ) echo "match ?o*" ;;  

    # 先頭文字が任意で、2文字目が'i'の文字列にマッチする  
    ?i* ) echo "match ?i*" ;;  

    * ) echo "match *" ;;  
esac  

実行結果。

$ bash sample.sh cat  
match ?a*  

$ bash sample.sh dog  
match ?o*  

$ bash sample.sh bird  
match ?i*  

$ bash sample.sh pig  
match ?i*  

グループによるマッチ

パターンに[]を使うと、マッチさせる文字をグループ化することが出来ます。

case "$1" in  
    # 先頭文字にa, b, cのいずれかの文字を含む文字列にマッチする  
    [abc]* ) echo "match [abc]*" ;;  

    # A~Zまたはa~zのいずれかの先頭文字を含む文字列にマッチする  
    # 正規表現とは違い小文字と大文字を区別しないので注意  
    [A-Z]* ) echo "match [A-Z]*" ;;  

    # "!"はカッコの中のいずれでもないという意味  
    # よってa, b, cのいずれでもない文字にマッチする  
    [!abc]* ) echo "match [!abc]*" ;;  
    * ) echo "match *" ;;  
esac  

実行結果。

$ bash sample.sh cat  
match [abc]*  

$ bash sample.sh dog  
match [A-Z]*  

$ bash sample.sh bird  
match [abc]*  

$ bash sample.sh pig  
match [A-Z]*  

$ bash sample.sh 123  
match [!A-Z]  

パターンに変数を使用する

パターンは変数に保存することも出来ます。

name="cat"  

pat_1="cat"  
pat_2="dog"  
pat_3="bird"  

case "$name" in  # <- nameには"cat"が入っている  
    "$pat_1" ) echo "match $pat_1" ;;  # <- これにマッチする  
    "$pat_2" ) echo "match $pat_2" ;;  
    "$pat_3" ) echo "match $pat_3" ;;  
    * ) echo "match *"  
esac  
# match cat  

ワイルドカードやグループを使う場合

ワイルドカードやグループを変数に書くことも出来ますが、それらを使う場合は変数をダブルクオートで囲まないようにします。
ダブルクオートで囲むと文字列として認識されます。

pat_1="c*"  
pat_2="[dD]og"  
pat_3="[bB]ird"  

case "$1" in  
    $pat_1 ) echo "match $pat_1" ;;  
    $pat_2 ) echo "match $pat_2" ;;  
    $pat_3 ) echo "match $pat_3" ;;  
    * ) echo "match *"  
esac  

実行結果。

$ bash sample.sh cat  
match c*  

$ bash sample.sh Dog  
match [dD]og  

$ bash sample.sh bird  
match [bB]ird  

使用例

Bashのcase文の使用例です。

メールアドレスのドメインごとに分岐する

メールアドレスのドメインごとに処理を分岐します。

case "$1" in  
    *@gmail.com ) echo "You are gmail user" ;;  
    *@docomo.co.jp ) echo "You are docomo user" ;;  
    *@ez.web.jp ) echo "You are AU user" ;;  
    * ) echo "Unknown" ;;  
esac  

実行結果。

$ bash a.sh ababa@gmail.com  
You are gmail user  

$ bash a.sh ababa@docomo.co.jp  
You are docomo user  

$ bash a.sh ababa@ez.web.jp  
You are AU user  

$ bash a.sh ababa@infoseek.jp  
Unknown  

終了確認プロンプト

「本当に終了しますか?」というプロンプトを出して入力に応じて処理を分岐します。

while true; do  
    echo "本当に終了しますか?(y/n)"  
    read line  

    case "$line" in  
        [yY]es | [yY] ) break ;;  
        [nN]o | [nN] ) echo "続行します。" ;;  
        * ) echo "不正な入力です。" ;;  
    esac  
done  

実行結果。

$ bash sample.sh  
本当に終了しますか?(y/n)  
n  
続行します。  
本当に終了しますか?(y/n)  
No  
続行します。  
本当に終了しますか?(y/n)  
ababa  
不正な入力です。  
本当に終了しますか?(y/n)  
Yes  

問題

Q1: case文のパターンに使えるデータを答えよ

  1. 数値
  2. 文字列
  3. パターン

Q2: case文のパターンで変数を使う場合の注意事項を答えよ

  1. ワイルドカードやグループを使う場合は変数をバッククオートで囲ってはならない
  2. ワイルドカードやグループを使う場合は変数をダブルクオートで囲ってはならない
  3. ワイルドカードやグループを使う場合は変数をダブルクオートで囲む

Q3: case文のパターンで「先頭にa, b, cのいずれかを含む文字列」として適当なパターンを答えよ

  1. [!abc]*
  2. [abc]*
  3. [0-9]*

正解

Q1: 1, 2, 3
Q2: 2
Q3: 2