Bashのcase文の書き方: パターンで分岐処理
目次
- Bashのcase文の書き方
- case文の構造
- 整数による分岐
- defaultパターン
- 文字列による分岐
- パターンにORを使う
- ワイルドカードによるマッチ
- 任意の1文字へのマッチ
- グループによるマッチ
- パターンに変数を使用する
- 使用例
- 問題
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
文のパターンに使えるデータを答えよ
数値
文字列
パターン
Q2: case
文のパターンで変数を使う場合の注意事項を答えよ
ワイルドカードやグループを使う場合は変数をバッククオートで囲ってはならない
ワイルドカードやグループを使う場合は変数をダブルクオートで囲ってはならない
ワイルドカードやグループを使う場合は変数をダブルクオートで囲む
Q3: case
文のパターンで「先頭にa, b, cのいずれかを含む文字列」として適当なパターンを答えよ
[!abc]*
[abc]*
[0-9]*
正解
Q1: 1, 2, 3
Q2: 2
Q3: 2