case 文の使用方法

case 文とは?

case 文は C言語や Java言語の switch 文に該当する制御文で、if 文と同じように処理を分岐するために使用されるものである。

分岐条件には判定対象となる 1つの値と、その値と照合される複数のパターンを指定する。case 文は値とパターンの照合を行い、パターンと一致した場合はそのパターンと共に指定されている処理を実行する。

case 文は if 文のように複雑な分岐条件を評価するのには向かないが、単純な分岐条件での多方向分岐に優れた文である。

case 値 in
  パターン1 ) 処理1 ;;
  パターン2 ) 処理2 ;;
  パターン3 ) 処理3 ;;
  パターンn ) 処理n ;;
esac

→ case 文は指定した値と複数のパターンとのマッチングにより多方向分岐を行う。

case 文には判定に使用される値と、それと照合される複数のパターン、およびそのパターンに一致した場合に実行する処理を指定する。

パターンは任意の数指定可能で、上から順に値との照合を行い、一番最初に一致したパターンに対応する処理を実行し case 文を終了する。

一致するパターンが 1つも存在しなければ、処理は一切実行されない。

case 文の使用例

パターンに文字列を指定する

case "$var" in
  "a" ) 処理1 ;;
  "bb" ) 処理1 ;;
  "c c c" ) 処理3 ;;
esac

→ パターンに固定の文字列を指定して完全一致マッチングを行う。

パターンに固定の文字列を指定した場合は、その文字列と完全に一致する場合のみ処理が実行される。

以下は、固定の文字列との照合を行う case 文を応用したシェルスクリプト (case_word.sh) の例。

#!/bin/bash

# "q" 入力以外で終了しないように無限ループにする。
while :
do
  read key
  case "$key" in
    "a" ) echo "aが入力されました。" ;;
    "bb" ) echo "bbが入力されました。" ;;
    "c c c" ) echo "c c cが入力されました。" ;;
    "q" ) echo "終了します。"
          break ;;
  esac
done

exit 0

このシェルスクリプト case_word.sh の実行結果は、以下のとおりとなる。

$ ./case_word.sh
a                ←キー入力
aが入力されました。
bb               ←キー入力
bbが入力されました。
c c c            ←キー入力
c c cが入力されました。
a aaa            ←キー入力
b b              ←キー入力
ccc              ←キー入力
q                ←キー入力
終了します。
$

「a」、「bb」、「c c c」および「q」が入力された場合のみメッセージが表示され、それ以外の入力では何も表示されていないことが確認できる。つまり、パターンに指定した文字列と完全に一致した場合のみ、処理が行われているということになる。

パターンにワイルドカードを指定する

case "$var" in
  a* ) echo "aで始まる文字列" ;;
  ?b* ) echo "2文字目がbの文字列" ;;
  [A-Z]* ) echo "大文字で始まる文字列" ;;
  [!xX]* ) echo "先頭がxではない文字列" ;;
  * ) echo "上記のいずれでもない文字列" ;;
esac

→ パターンにワイルドカードを使用して部分一致マッチングを行う。

パターンには固定の文字列のみではなく、ワイルドカードを使用することも可能だ。

以下は、ワイルドカードを使用した照合を行う case 文を応用したシェルスクリプト (case_wc.sh) の例。

#!/bin/bash

while :
do
  read key
  case "$key" in
    "q" ) echo "終了します。"
          break ;;

    # "*" は任意の文字列(空文字を含む)を意味する。
    a* ) echo "aで始まる文字列" ;;

    # "?" は任意の1文字を意味する。
    ?b* ) echo "2文字目がbの文字列" ;;

    # "[]" は括弧の中の文字のいずれかを意味する。"-" で範囲を指定することも可能。
    # ここでは A~Z のいずれか 1 文字という意味になる。
    [A-Z]* ) echo "大文字で始まる文字列" ;;

    # "!" が付くと括弧の中のいずれでもないという意味になる。
    # つまり x でも y でも z でもない文字という意味になる。
    [!xyz]* ) echo "先頭がx、y、zではない文字列" ;;

    * ) echo "上記のいずれでもない文字列" ;;
  esac
done

exit 0

このシェルスクリプト case_wc.sh の実行結果は、以下のとおりとなる。

$ ./case_wc.sh
abc                    ←キー入力
aで始まる文字列
bbc                    ←キー入力
2文字目がbの文字列
ABC                    ←キー入力
大文字で始まる文字列
www                    ←キー入力
先頭がx、y、zではない文字列
xyz                    ←キー入力
上記のいずれでもない文字列
Abc                    ←キー入力
2文字目がbの文字列
q                      ←キー入力
終了します。
$

ワイルドカードを使用すると、柔軟なパターンを作成することができる。シェルスクリプト中の case 文に abc というパターンは存在していないが、a* と一致するためメッセージが表示される。

Abc?b*[A-Z]* の両方と一致するが、?b* のパターンの方が上にあるため、そのパターンの処理が優先される。

パターンに OR 条件を使用する

case "$var" in
  "yes" | "Yes" | "YES" ) echo "イエスが入力されました" ;;
  [nN]o | "NO" ) echo "ノーが入力されました" ;;
  * ) echo "イエスでもノーでもありません" ;;
esac

→ OR 条件を使用して、複数のパターンをまとめて一度に指定する。

OR 条件を使用して、複数のパターンをまとめてマッチングを行うことも可能である。

上記の例では、イエスは、

  • 全て小文字
  • 先頭のみ大文字
  • 全て大文字

のいずれかであれば処理を行う。

ノーは2種類のパターンしか指定していないが、[nN]onoNo に一致するため、イエスと同く「全て小文字」、「先頭のみ大文字」、「全て大文字」のいずれかであれば処理を行う。

以下は、OR 条件を使用した照合を行う case 文を応用したシェルスクリプト (case_or.sh) の例。

#!/bin/bash

echo "ループに入ります..."

while :
do
  # -n を指定するとメッセージ表示後に改行しない。
  echo -n "処理を継続しますか?: "
  read key
  case "$key" in
    # yes, Yes, YES の 3 パターンに一致。
    [yY]es | YES ) echo "イエスが入力されました。処理を継続します。" ;;

    # no, No, NO の 3 パターンに一致。
    [nN]o | NO ) echo "ノーが入力されました。処理を終了します。"
                 break ;;

    # 全ての文字列に一致。
    # つまり上記 6 パターンの何れでもない文字列が入力された場合の処理となる。
    * ) echo "イエスかノーを入力してください。" ;;
  esac
done

exit 0

このシェルスクリプト case_wc.sh の実行結果は、以下のとおりとなる。

$ ./case_or.sh
ループに入ります...
処理を継続しますか?: aaa
イエスかノーを入力してください。
処理を継続しますか?: yes
イエスが入力されました。処理を継続します。
処理を継続しますか?: Yes
イエスが入力されました。処理を継続します。
処理を継続しますか?: YES
イエスが入力されました。処理を継続します。
処理を継続しますか?: yEs
#↑「E」のみ大文字であるイエスのパターンはないため、イエスとはみなされない。

イエスかノーを入力してください。
処理を継続しますか?: yES
#↑「y」のみ小文字であるイエスのパターンはないため、イエスとはみなされない。

イエスかノーを入力してください。
処理を継続しますか?: nO
#↑「O」のみ大文字であるノーのパターンはないため、ノーとはみなされない。

イエスかノーを入力してください。
処理を継続しますか?: no
ノーが入力されました。処理を終了します。
$

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

case "$var" in
  "$PATTERN_1" ) 処理1 ;;
  "$PATTERN_2" ) 処理2 ;;
  $PATTERN_3 ) 処理3 ;;
esac

→ パターンに文字列やワイルドカードが設定された変数を指定する。

パターンは変数であっても問題はない。case 文は展開された変数の値を元に処理を行うので、変数に設定されている値がワイルドカードだった場合は、その変数はワイルドカードとして機能する

ただし、ワイルドカードとして機能させるには、上記例の処理3に対応するパターンのように、その変数をクォートしてはいけない

以下は、変数をパターンとして指定する case 文を応用したシェルスクリプト (case_var.sh) の例。

#!/bin/bash

# パターンに指定する変数を定義する。
PATTERN_1="hoge"
PATTERN_2="fuga"
ASTERISK="*"
AtoZ="[A-Z]"

case "$1" in
  # 変数で文字列を指定する。
  "$PATTERN_1" ) echo "$PATTERN_1と一致しました。" ;;
  "$PATTERN_2" ) echo "$PATTERN_2と一致しました。" ;;

  # [A-Z] を変数で指定する。
  $AtoZ        ) echo "$AtoZと一致しました。" ;;

  # クォートしているのでワイルドカードではなく普通の文字列となる。
  "$ASTERISK"  ) echo "文字の$ASTERISKと一致しました。" ;;

  # * を変数で指定する。
  $ASTERISK    ) echo "ワイルドカードの$ASTERISKと一致しました。" ;;
esac

exit 0

このシェルスクリプト case_var.sh の実行結果は、以下のとおりとなる。

$ ./case_var.sh hoge
hogeと一致しました。
$ ./case_var.sh fuga
fugaと一致しました。
#↑変数を指定した場合も文字列を直接指定した場合と同じように機能する。

$ ./case_var.sh A
[A-Z]と一致しました。
#↑変数に設定したワイルドカードが正常に機能している。

$ ./case_var.sh Z
[A-Z]と一致しました。
#↑上に同じ。

$ ./case_var.sh "[A-Z]"
ワイルドカードの*と一致しました。
#↑変数 AtoZ はクォートされていないので、ワイルドカードとして機能しているためこの文字とは一致しない。
#その代わり、クォートされていない変数 ASTERISK と一致した。

$ ./case_var.sh "*"
文字の*と一致しました。
#↑クォートした変数 ASTERISK と一致している。