case文
前回、一対多の判定の場合は「if」文ではなく、「case」文を使うべきだと書きましたが、
今回はそれを実証してみたいと思います。
今回からはスクリプトの要件を以下に変えてみます。
・第一オプションが「Windows」の場合、「Hello Bill Gates!!」と表示する。
・第一オプションが「Linux」の場合、「Hello Linus!!」と表示する。
・第一オプションが「OpenBSD」の場合、「Hello Theo!!」と表示する。
・第一オプションが「Solaris」の場合、「Hello Bill Joy!!」と表示する。
・第一オプションが「emacs」の場合、「Hello RMS!!」と表示する。
・第一オプションが「sendmail」の場合、「Hello Eric!!」と表示する。
・第一オプションが上記以外の場合、「Hello World!!」と表示する。
※若干、Hello Worldから趣旨が外れてきてる気がしないでもないですが、まぁいいでしょう。
まず、前回書いたスクリプトを改変します。
前回と同じく、「elif」文で選択肢を増やす形です。
エディタで「helloworld4.sh」を作成し、以下を記述してみましょう。
#!/bin/bash
## 変数初期化
V_OPTION=$1 ## 第一オプションを代入
## オプション判定
## 第一オプションが「Windows」の場合、「Hello Bill Gates!!」と出力
## 第一オプションが「Linux」の場合、「Hello Linus!!」と出力
## 第一オプションが「OpenBSD」の場合、「Hello Theo!!」と出力
## 第一オプションが「Solaris」の場合、「Hello Bill Joy!!」と出力
## 第一オプションが「emacs」の場合、「Hello RMS!!」と出力
## 第一オプションが「sendmail」の場合、「Hello Eric!!」と出力
## 第一オプションが上記以外の場合、「Hello World!!」と出力
if [ "${V_OPTION}" = "Windows" ]
then
echo "Hello Bill Gates!!"
elif [ "${V_OPTION}" = "Linux" ]
then
echo "Hello Linus!!"
elif [ "${V_OPTION}" = "OpenBSD" ]
then
echo "Hello Theo!!"
elif [ "${V_OPTION}" = "Solaris" ]
then
echo "Hello Bill Joy!!"
elif [ "${V_OPTION}" = "emacs" ]
then
echo "Hello RMS!!"
elif [ "${V_OPTION}" = "sendmail" ]
then
echo "Hello Eric!!"
else
echo "Hello World!!"
fi
実行結果はこんな感じです。
# ./helloworld4.sh Windows Hello Bill Gates!! # ./helloworld4.sh Linux Hello Linus!! # ./helloworld4.sh OpenBSD Hello Theo!! # ./helloworld4.sh Solaris Hello Bill Joy!! # ./helloworld4.sh emacs Hello RMS!! # ./helloworld4.sh sendmail Hello Eric!! # ./helloworld4.sh Hello World!! #
実行結果は想定通りです。
続いて、「case」文を使った実装です。
「case」文は、以下の様な構文で記述します。
case 判定対象変数 in 判定条件1) 判定条件1の処理内容 ;; 判定条件2) 判定条件2の処理内容 ;; *) #例外処理 例外処理内容 ;; esac
一つの判定対象に対して、複数の判定条件を記述していきます。
字下げにもよりますが、パッと見た目でも、判定条件毎の処理が判りやすいです。
また判定項目が増えた際も、判定対象は変わりませんので、判定条件を増やすだけで対応できます。
では、新たに「helloworld5.sh」を作成し、以下を記述してみましょう。
#!/bin/bash
## 変数初期化
V_OPTION=$1 ## 第一オプションを代入
## オプション判定
## 第一オプションが「Windows」の場合、「Hello Bill Gates!!」と出力
## 第一オプションが「Linux」の場合、「Hello Linus!!」と出力
## 第一オプションが「OpenBSD」の場合、「Hello Theo!!」と出力
## 第一オプションが「Solaris」の場合、「Hello Bill Joy!!」と出力
## 第一オプションが「emacs」の場合、「Hello RMS!!」と出力
## 第一オプションが「sendmail」の場合、「Hello Eric!!」と出力
## 第一オプションが上記以外の場合、「Hello World!!」と出力
case "${V_OPTION}" in
Windows)
echo "Hello Bill Gates!!"
;;
Linux)
echo "Hello Linus!!"
;;
OpenBSD)
echo "Hello Theo!!"
;;
Solaris)
echo "Hello Bill Joy!!"
;;
emacs)
echo "Hello RMS!!"
;;
sendmail)
echo "Hello Eric!!"
;;
*)
echo "Hello World!!"
;;
esac
見て判ると思いますが、明らかに可読性が上がっていますよね。
実行結果は以下の通りです。
# ./helloworld5.sh Windows Hello Bill Gates!! # ./helloworld5.sh Linux Hello Linus!! # ./helloworld5.sh OpenBSD Hello Theo!! # ./helloworld5.sh Solaris Hello Bill Joy!! # ./helloworld5.sh emacs Hello RMS!! # ./helloworld5.sh sendmail Hello Eric!! # ./helloworld5.sh Hello World!! #
「if」文と同じく、想定通りに実装されているようです。
では、処理速度はどうなのでしょうか?
6項目程度では、体感できる差は無いと言ってよいでしょう。
ですが、詳細な処理内容を比較すれば、差は歴然です。
前々回、バグを確認した時と同じ様に、詳細な処理ログを見てみましょう。
スクリプト1行目に「-x」を付与してから、第一オプションに何も指定せずに実行してみてください。
・if文の場合
# ./helloworld4.sh + V_OPTION= + '[' '' = Windows ']' + '[' '' = Linux ']' + '[' '' = OpenBSD ']' + '[' '' = Solaris ']' + '[' '' = emacs ']' + '[' '' = sendmail ']' + echo 'Hello World!!' Hello World!! #
オプションに何も指定していない場合は例外処理になりますので、if文の実装だと全ての条件文(if文、elif文)を処理しないと、「else」まで辿り着く事ができません。
今回のスクリプトだと、6回の条件文(if文、elif文)を通過して、やっと例外処理(else)に辿り着く事になります。
・case文の場合
# ./helloworld5.sh
+ V_OPTION=
+ case "${V_OPTION}" in
+ echo 'Hello World!!'
Hello World!!
#
ところがcase文の場合、1回の判定で例外処理を行っています。
その為、項目が増えれば増える程、処理速度の差が開いていきます。
実際、case文でそこまで多くの項目を判定する事は無いと思いますが、この判定をループ処理で行う事は多々あります。
そうなった場合、ループ処理回数が増えれば増える程、処理速度は明確に違ってきます。
複数の選択肢がある様な条件判定の場合は、率先してcase文を使う様に心がけましょう。
