今回は、文字列のパターンで分岐する「case」を解説します。複数の条件で“Aなら~する”、“Bなら~する”、“Cなら~する”のように処理を分けたい場合は、「if ~ elif ~ elif ~……」で書くこともできますが、文字列のパターンで分岐する場合は「case」が便利です。
case文は以下のように書きます。「case」で始まり、「case」を逆から書いた「esac」で終わります。
- case 文字列 in
- パターン1) 文字列がパターン1に該当したときのコマンド ;;
- パターン2) 文字列がパターン2に該当したときのコマンド ;;
- *) 文字列がどのパターンにも該当しなかったときのコマンド ;;
- esac
分岐は「パターン) パターンに合致した場合の処理」のように書きます。パターンには「*」や「?」などの記号を使うことができます。
パターンに合っているかどうかは、上から順番にチェックされます。1つ目のパターンに一致していれば、それ以降は処理されません。従って、最後に「*)」というパターンを置くことで、“全てに該当しなかった場合”という処理を書くことができます。
「;;」は、「パターン) 処理」という組み合わせのリストの“区切り”を意味しています。従って、最後の「;;」は省略可能です。
なお、「in」「)」「;;」の前後の改行は自由です。複数のコマンドを実行したい場合は、改行または「;」で区切ります。
今回は「引数の内容に応じて処理を変える」という動作を試してみましょう。シェルスクリプトの中でキー入力を受け取る方法については、次回解説します。
例えば、1つ目の引数が「y」なら「echo "YES"」と「echo "OK"」の2つを実行し、「n」なら「echo "NO"」を実行、それ以外なら「echo "undefined"」を実行するとしてみましょう。次のようになります。
なお、文字列である「"y"」と「"n"」の引用符(")は省略可能です。最後の「*」はパターンとして指定しているので、引用符を付けない点に注意してください。
- #! /bin/bash
- case "$1" in
- "y")
- echo "YES"
- echo "OK"
- ;;
- "n")
- echo "NO"
- ;;
- *)
- echo "undefined";;
- esac
- 不明
- $ chomod +x showyesno
- $ ./showyesno y
- YES
- OK
- #(引数が「y」だったので「YES」と「OK」が表示された)
- $ ./showyesno n
- NO
- #(引数が「n」だったので「NO」が表示された)
- $ ./showyesno aaa
- undefined
- #(引数が「y」でも「n」でもないので「undefined」が表示された)
先ほどの例(showyesno)では、「in」「)」「;;」で改行していますが、ここの改行は自由です。例えば、それぞれのパターンを1行にするのであれば、以下のようになります。
「"y")」のパターンでは実行するコマンドが2つあるので、「;」で区切っています。なお、最後の「;;」は省略可能です。
- #! /bin/bash
- case "$1" in
- "y") echo "YES"; echo "OK";;
- "n") echo "NO";;
- *) echo "undefined";;
- esac
さらに短く、1行に全てをまとめることもできます。この場合、esac直前の「;;」は省略できません。
- #! /bin/bash
- case "$1" in "y") echo "YES"; echo "OK";; "n") echo "NO";; *) echo "undefined";; esac
case文全てを1行にするのはやや極端ですが、それぞれの処理が短く、内容が決まっているならば、ある程度まとめた方が読みやすくなるかもしれません。
一方、これからコマンドを追加する、パターンを複雑にするなど、スクリプトの編集を考えている場合は、最初の書き方のように、パターンや各コマンドが独立した行になっている方が扱いやすいでしょう。
パターンの部分には「*」の他、「?」(任意の1文字)や「[~]」([]内のいずれか1文字、範囲指定も可能)を使うことができます。
「[]」を使って、「y」と「n」それぞれ、大文字と小文字のどちらでも指定できるようにすると以下のようになります。パターン指定なので、「"y"」のような引用符は不要である点に注意してください。
- #! /bin/bash
- case "$1" in
- [Yy]) #Yまたはy(パターン指定なので引用符は付けない)
- echo "YES"
- echo "OK"
- ;;
- [Nn]) #Nまたはn
- echo "NO"
- ;;
- *)
- echo "undefined";;
- esac
- $ ./showyesno y
- YES
- OK
- #(引数が「y」だったので「YES」と「OK」が表示された)
- $ ./showyesno Y
- YES
- OK
- #(引数が大文字の「Y」でも「YES」と「OK」が表示された)
複数のパターンを使いたい場合は「|」で区切って並べます。例えば、「Y」「y」の他に「yes」でも指定できるようにするならば、「[Yy]|"yes"」のようにします。
- #! /bin/bash
- case "$1" in
- [Yy]|"yes") #Y、yまたはyesという文字列
- echo "YES"
- echo "OK"
- ;;
- [Nn]|"no") #N、nまたはnoという文字列
- echo "NO"
- ;;
- *)
- echo "undefined";;
- esac
先ほどの例では「yes」には対応しましたが、「YES」や「Yes」には対応していません。
少々読みにくくなりますが、「[Yy][Ee][Ss]」のように書くことで、大文字と小文字に対応させることができます。これは、1文字目が「Y」または「y」、2文字目が「E」または「e」、3文字目は「S」または「s」という意味です。また、1文字だけで「Y」または「y」というのも有効にしておきたいとすると、次のようになります。
- #! /bin/bash
- case "$1" in
- [Yy]|[Yy][Ee][Ss])
- echo "YES"
- echo "OK"
- ;;
- [Nn]|[Nn][Oo])
- echo "NO"
- ;;
- *)
- echo "undefined";;
- esac
大文字と小文字の区別をなくすシェルオプション「nocasematch」を有効にすると、case文のパターン判定でも大文字と小文字が区別されなくなります。
ここではシェルスクリプトの先頭で、「shopt」コマンド(bashの組み込みコマンド)で「nocasematch」を有効にしています。この設定はシェルスクリプトの中でのみ有効です。
- #! /bin/bash
- shopt -s nocasematch #大文字と小文字を区別しない
- case "$1" in
- "y"|"yes")
- echo "YES"
- echo "OK"
- ;;
- "n"|"no")
- echo "NO"
- ;;
- *)
- echo "undefined";;
- esac
元の文字列(ここでは$1)を、いったん全て大文字または小文字に変換した上で比較するという方法もあります。
例えば、「tr」コマンドならば、「tr A-Z a-z」で大文字を全て小文字に、「tr a-z A-Z」で小文字を全て大文字に変換できます。
trコマンドは標準入力から受け取った文字列を処理するので、echoコマンドとパイプでtrコマンドに渡します。具体的には「`echo $1|tr A-Z a-z`」のように指定します。
このように、case文とバッククオートを組み合わせることで、コマンドの実行結果を使ってパターン分岐させることができます。
- #! /bin/bash
- case `echo "$1"|tr A-Z a-z` in #引数を小文字に変換
- "y"|"yes")
- echo "YES"
- echo "OK"
- ;;
- "n"|"no")
- echo "NO"
- ;;
- *)
- echo "undefined";;
- esac
bashのバージョン4以降の場合、「${変数名^^}」で全て大文字、「${変数名,,}」で全て小文字、のような値の取得が可能です。
そこで、trコマンドを使わなくても、以下のようにすることで引数を小文字に統一できます。
- #! /bin/bash
- case ${1,,} in #引数を全て小文字で取得
- "y"|"yes")
- echo "YES"
- echo "OK"
- ;;
- "n"|"no")
- echo "NO"
- ;;
- *)
- echo "undefined";;
- esac
この他にも以下のような指定方法があります。全体を変更するものと、先頭文字だけを変更(2文字目以降には何もしない)するものがあります。
指定方法 | 意味 | 変換例 | |||
---|---|---|---|---|---|
ABC | abc | Abc | aBC | ||
${変数名^} | 1文字目だけ大文字にする | ABC | Abc | Abc | ABC |
${変数名^^} | 全て大文字にする | ABC | ABC | ABC | ABC |
${変数名,} | 1文字目だけ小文字にする | aBC | abc | abc | aBC |
${変数名,,} | 全て小文字にする | abc | abc | abc | abc |
${変数名~} | 1文字目だけ大文字小文字を反転させる | aBC | Abc | abc | ABC |
${変数名~~} | 大文字小文字を全て反転させる | abc | ABC | aBC | Abc |
西村 めぐみ(にしむら めぐみ)
もともとはDOSユーザーで「DOS版UNIX-like tools」を愛用。ソフトハウスに勤務し生産管理のパッケージソフトウェアの開発およびサポート業務を担当、その後ライターになる。著書に『図解でわかるLinux』『らぶらぶLinuxシリーズ』『Accessではじめるデータベース超入門[改訂2版]』『macOSコマンド入門』など。地方自治体の在宅就業支援事業にてMicrosoft Officeの教材作成およびeラーニング指導を担当。会社などの“PCヘルパー”やピンポイント研修なども行っている。
Copyright © ITmedia, Inc. All Rights Reserved.
Linux �� OSS 險倅コ九Λ繝ウ繧ュ繝ウ繧ー