Bash スクリプトでケース ステートメントを使用する方法

  • Bash の case ステートメントは、長い if-then-else ステートメントと比較して、スクリプトの読み取りとメンテナンスが容易になります。
  • Bash の case ステートメントは、句の式とパターンを照合し、それに応じてステートメントを実行します。
  • 1 つの句に複数のパターンを使用できるため、スクリプトをより簡潔で効率的にすることができます。数字または数値変数も case ステートメントで使用できます。

Bash の case ステートメントは強力でありながら、簡単に記述できます。古い Linux スクリプトを再確認するときに、長い if-then-else ステートメントではなく、case ステートメントを使用したことを嬉しく思うでしょう。

case ステートメント

ほとんどのプログラミング言語には、switch ステートメントまたは case ステートメントのバージョンがあります。これらは、変数の値に応じてプログラムの実行フローを指示します。通常、変数の想定される値のそれぞれに対して定義された実行の分岐と、その他のすべての値に対するキャッチオールまたはデフォルトの分岐があります。

論理的な機能は、ifステートメントのいずれによっても以前には処理されていないすべてをキャッチする else ステートメントを持つ、長い if-then ステートメントのシーケンスに似ています。

case の Bash 実装では、式を句のいずれかと一致させようとします。これは、各句を順番に調べて、一致するパターンを見つけようとします。句のパターンは文字列ですが、直感に反して、式として数値を使用することはできません。

一般的な case

case ステートメントの一般的な形式は次のとおりです。

<code>case expression in

pattern-1)
statement
;;

pattern-2)
statement
;;
.
.
.

pattern-N)
statement
;;

*)
statement
;;
esac
  • case ステートメントは case キーワードで始まり、esacキーワードで終わる必要があります。
  • 式が評価され、一致が見つかるまで各句のパターンと比較されます。
  • 一致する句のステートメントまたはステートメントが実行されます。
  • 二重セミコロン「;;」は、句を終了するために使用されます。
  • パターンが一致し、その句のステートメントが実行されると、他のすべてのパターンは無視されます。
  • 句の数に制限はありません。
  • アスタリスク「*」は、デフォルトのパターンを示します。式が case ステートメントの他のパターンと一致しない場合、デフォルトの句が実行されます。

簡単な例

このスクリプトは、架空の店舗の営業時間について説明します。+"%a"形式文字列を使用してdateコマンドを使用し、短縮された曜日名を取得します。これはDayName変数に格納されます。

<code>#!/bin/bash

DayName=$(date +"%a")

echo "Opening hours for $DayName"

case $DayName in

Mon)
echo "09:00 - 17:30"
;;

Tue)
echo "09:00 - 17:30"
;;

Wed)
echo "09:00 - 12:30"
;;

Thu)
echo "09:00 - 17:30"
;;

Fri)
echo "09:00 - 16:00"
;;

Sat)
echo "09:30 - 16:00"
;;

Sun)
echo "Closed all day"
;;

*)
;;
esac

そのテキストをエディターにコピーし、「open.sh」という名前のファイルとして保存します。

chmod コマンドを使用して実行可能にする必要があります。この記事で作業するときに作成するすべてのスクリプトに対してそれを行う必要があります。

chmod +x open.sh

これでスクリプトを実行できるようになりました。

./open.sh

スクリーンショットが撮影された日はたまたま金曜日でした。つまり、DayName 変数には文字列「Fri」が含まれます。これは、「Fri)」句の「Fri」パターンと一致します。

句のパターンを二重引用符で囲む必要はありませんが、囲んでも害はありません。ただし、パターンにスペースが含まれている場合は、二重引用符を使用する必要があります。

デフォルトの句は空のままになっています。前の句のいずれとも一致しないものはすべて無視されます。

そのスクリプトは機能し、読みやすいですが、長くて繰り返しがあります。そのタイプの case ステートメントは非常に簡単に短縮できます。

句に複数のパターンを使用する

case ステートメントの本当に優れた機能は、各句に複数のパターンを使用できることです。式がそれらのパターンのいずれかと一致する場合、その句のステートメントが実行されます。

これは、1 か月に何日あるかを教えてくれるスクリプトです。答えは 30 日、31 日、2 月は 28 日または 29 日の 3 つしかありません。したがって、12 か月ありますが、句は 3 つしか必要ありません。

このスクリプトでは、ユーザーに月の名前を入力するように求めます。パターンマッチングを大文字と小文字を区別しないようにするには、shopt コマンドを「-s nocasematch」オプションとともに使用します。入力に大文字、小文字、またはその両方が混在していても問題ありません。

<code>#!/bin/bash

shopt -s nocasematch

echo "1 か月の名前を入力してください"
read month

case $month in

February)
echo "$month には 28 日または 29 日あります"
;;

April | June | September | November)
echo "$month には 30 日あります"
;;

January | March | May | July | August | October | December)
echo "$month には 31 日あります"
;;

*)
echo "不明な月: $month"
;;
esac

2 月はそれ自体が句を持ち、他のすべての月は 30 日または 31 日のどちらかであるかによって 2 つの句を共有します。複数パターンの句は、区切り記号としてパイプ記号「|」を使用します。デフォルトのケースは、スペルの悪い月をキャッチします。

これを「month.sh」という名前のファイルに保存し、実行可能にしました。

chmod +x month.sh

スクリプトを数回実行し、大文字と小文字のどちらを使用しても問題がないことを示します。

./month.sh

スクリプトに大文字と小文字の差を無視するように指示したため、正しくスペルが書かれた月の名前は 3 つの主要な句のいずれかによって処理されます。スペルの悪い月は、デフォルトの句によってキャッチされます。

case ステートメントで数字を使用する

式として数字または数値変数を使用することもできます。このスクリプトは、ユーザーに 1..3 の範囲の数字を入力するように求めます。各句のパターンが文字列であることを明確にするために、二重引用符で囲みました。これにもかかわらず、スクリプトはユーザーの入力を適切な句に一致させます。

<code>#!/bin/bash

echo "1、2、または 3 を入力してください: "
read Number

case $Number in

"1")
echo "句 1 と一致します"
;;

"2")
echo "句 2 と一致します"
;;

"3")
echo "句 3 と一致します"
;;

*)
echo "デフォルト句と一致します"
;;
esac

./number.sh

for ループで case ステートメントを使用する

case ステートメントは、単一の式のパターンを一致させようとします。処理する式が多い場合は、case ステートメントを for ループ内に入れることができます。

このスクリプトは、ls コマンドを実行してファイルのリストを取得します。for ループでは、ファイル拡張子を取り出すために、各ファイルにファイル グロビング(正規表現に似ていますが異なります)が順番に適用されます。これは、Extension 文字列変数に格納されます。

case ステートメントは、Extension 変数を句に一致させようとする式として使用します。

<code>#!/bin/bash

for File in $(ls)

do
# ファイル拡張子を取り出す
Extension=${File##*.}

case "$Extension" in

sh)
echo " シェル スクリプト: $File"
;;

md)
echo " マークダウン ファイル: $File"
;;

png)
echo "PNG 画像ファイル: $File"
;;

*)
echo "不明: $File"
;;
esac
done

このテキストを「filetype.sh」という名前のファイルに保存し、実行可能にしてから、次を使用して実行します。

./filetype.sh

私たちのミニマリストのファイル タイプ識別スクリプトが機能します。

case ステートメントで終了コードを処理する

正常に動作するプログラムは、終了時に終了コードをシェルに送信します。従来のスキームでは、終了コード値 0 を使用して問題のない実行を示し、1 以上の値を使用してさまざまなタイプのエラーを示します。

多くのプログラムは、0 と 1 のみを使用します。すべてのエラー条件を単一の終了コードにまとめると、問題の特定が困難になりますが、一般的な方法です。

私たちは、ランダムに 0 または 1 の終了コードを返す「go-geek」という小さなプログラムを作成しました。この次のスクリプトは、go-geek を呼び出します。$? シェル変数を使用して終了コードを取得し、それを case ステートメントの式として使用します。

実際のスクリプトは、終了コードを生成したコマンドの成功または失敗に応じて適切な処理を行います。

<code>
#!/bin/bash

go-geek

case $? in

"0")
echo "応答は: 成功"
echo "ここで適切な処理を行う"
;;

"1")
echo "応答は: エラー"
echo "ここで適切なエラー処理を行う"
;;

*)
echo "認識されない応答: $?"
;;
esac

これを「return-code.sh」というスクリプトに保存し、実行可能にします。go-geek コマンドの代わりに別のコマンドを代用する必要があります。存在しないディレクトリに cd して終了コード 1 を取得し、次にスクリプトを編集してアクセス可能なディレクトリに cd して終了コード 0 を取得することができます。

スクリプトを数回実行すると、さまざまな終了コードが case ステートメントによって正しく識別されていることがわかります。

./return-code.sh

読みやすさが保守性を高める

古い Bash スクリプトに戻って、特に他の誰かが書いた場合、それらが何をしているのかを理解するのは困難です。古いスクリプトの機能を変更することはさらに困難です。

case ステートメントは、明確で簡単な構文で分岐ロジックを提供します。これは、双方にメリットがあります。