caseコマンドはある文字列に対して、パターンマッチを行っていき、コマンドの処理を分岐できます。
ファイルの拡張子によってコマンドの実行を分けたい場合やそれぞれ特定のファイル名ごとに処理の実行を分けたい場合に利用できます。
caseの構文
caseコマンドの基本的な構文
1 |
case word in [ [(] pattern [| pattern]…) command-list ;;]… esac |
シェルスクリプトでよく見る形は以下の通りです。
1 2 3 4 5 |
case word in pattern ) command-list;; pattern1 | pattern2 ) command-list;; * ) command-list;; esac |
また、patternはカッコで囲むこともできます。
1 2 3 4 5 |
case word in ( pattern ) command-list;; ( pattern ) command-list;; ( * ) command-list;; esac |
パターンマッチで用いる特殊な文字には以下のようなものがあります。
パターンマッチで用いる特殊な文字
記号 | 意味 |
* | 0文字以上の任意の文字列 |
? | 任意の一文字 |
[] | カッコ内の文字の一文字 例) [abc], [a-z] 等 |
[:class:] | 文字クラスに当てはまる一文字 例)[:alnum:], [:blank:] 等 |
caseコマンドの利用例
caseコマンドはコマンドの処理を分岐できます。文字列に対して、パターンマッチを行い、最初にパターンマッチに成功した処理を行います。基本的に"case"の後に変数を記述し、"in"の後に文字列パターンと処理を列挙し、"easc"で終了します。
処理は";;"または";&"または";;&"で区切っていきます。";&"や";;&"はパターンマッチした後でもcaseコマンドの処理を終了せずに続けて条件を無視したコマンドの処理やパターンマッチを行った処理を行うことができます。詳しくは次の段落で後述します。
複数のパターンで処理が同じ場合は"|"を利用することで複数のパターンを記述できます。
case.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#!/bin/bash while read fname; do case $fname in *.txt) echo "$fname: txt";; *.dat) echo "$fname: dat";; *.jpg | *.jpeg) echo "$fname: jpg or jpeg";; *) echo "$fname: no match";; esac done |
list.txt
1 2 3 4 5 6 |
aaa.dat bbb.jpg ccc.jpeg ddd.sh eee.txt fff |
実行結果
1 2 3 4 5 6 7 |
$ ./case.sh < list.txt aaa.dat: dat bbb.jpg: jpg or jpeg ccc.jpeg: jpg or jpeg ddd.sh: no match eee.txt: txt fff: no match |
当てはまったパターンの後に別のパターンを実行
パターンマッチに成功した後に別のパターンについても条件が合うかどうかを判定したいときは処理の区切り文字に";;"ではなく、";&"や";;&"を用います。
";&"は条件を無視して次のパターンの処理を行います。
";;&"は次以降のパターンマッチも行い、マッチングするならばコマンドの処理を行います。
以下のスクリプトは読み込まれた単語に対してどの母音が含まれているかを表示します。
case_vowel.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#!/bin/bash while read name; do case $name in *a*) printf "a";;& *i*) printf "i";;& *u*) printf "u";;& *e*) printf "e";;& *o*) printf "o";;& *) echo ": $name";; esac done |
item.txt
1 2 3 4 5 |
apple melon yuzu banana lemon |
実行結果
1 2 3 4 5 6 |
$ ./case_vowel.sh < item.txt ae: apple eo: melon u: yuzu a: banana eo: lemon |
";&"を用いると次のパターンの条件を無視して処理が実行されます。
case2.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#!/bin/bash while read name; do case $name in *a*) printf "a";& z) printf "z";;& *u*) printf "u";& x) printf "x";;& *) echo ": $name" echo "--";; esac done |
item2.txt
1 2 3 4 5 |
apple yuzu lemon x z |
実行結果
1 2 3 4 5 6 7 8 9 10 11 |
$ ./case2.sh < item2.txt az: apple -- ux: yuzu -- : lemon -- x: x -- z: z -- |
caseコマンドの処理の区切り文字を変更すると微妙に動作が変わることも覚えておくとよいでしょう。