Bashプログラミング
 Computer >> コンピューター >  >> プログラミング >> Bashプログラミング

Bashのcase文を徹底解説!実務で使える5つの実践例

Bashのcase文を徹底解説!実務で使える5つの実践例Bashシェルのcase文は、C言語のswitch文に似た構文で、整数や文字列などの単純な値を判定するのに適しています。

case文はループ構造ではないため、同じコードブロックを繰り返し実行することはありません。代わりに、条件を評価してプログラムの処理フローを制御する役割を担います。

この記事では、Bashのcaseコマンドを実践的な5つの例とともに詳しく見ていきましょう。

case文の基本構文

Bashのcase文では、ワイルドカード文字を含むパターンに対して文字列を照合できます。case文は、if-then-elseステートメントをより簡潔に書ける最もシンプルな形式と言えます。

Bash case文の基本構文は以下の通りです。

case expression in
    pattern1 )
        statements ;;
    pattern2 )
        statements ;;
    ...
esac

case文の重要なポイントは以下の通りです。

  • まず式(expression)が展開され、各パターンとの照合が順番に試みられます。
  • 一致するパターンが見つかると、二重セミコロン(;;)までの関連するすべてのステートメントが実行されます。
  • 最初に一致した時点でcase文は終了し、直前に実行されたコマンドの終了ステータスが返されます。
  • どのパターンにも一致しなかった場合、case文の終了ステータスは0になります。

例1:プロセスへのシグナル送信

次のスクリプトは、シグナル番号とプロセスIDを引数として受け取り、シグナル名を使って指定したプロセスIDへシグナルを送信します。case文の基本的な使い方を示すサンプルです。

$ cat signal.sh
#!/bin/bash

if [ $# -lt 2 ]
then
        echo "Usage : $0 Signalnumber PID"
        exit
fi

case "$1" in

1)  echo "Sending SIGHUP signal"
    kill -SIGHUP $2
    ;;
2)  echo  "Sending SIGINT signal"
    kill -SIGINT $2
    ;;
3)  echo  "Sending SIGQUIT signal"
    kill -SIGQUIT $2
    ;;
9) echo  "Sending SIGKILL signal"
   kill -SIGKILL $2
   ;;
*) echo "Signal number $1 is not processed"
   ;;
esac

このスクリプトのポイントは以下の通りです。

  • $1と$2には、それぞれシグナル番号とプロセスIDが渡されます。
  • killコマンドを使って、対応するシグナルを指定したプロセスIDに送信します。
  • 最後の比較「*」はデフォルトケース(ワイルドカード)であり、どんな値にも一致します。

このスクリプトの使い方:sleepコマンドのプロセスIDを調べ、そのプロセスIDに対してkillシグナルを送ってプロセスを終了させてみましょう。

$ sleep 1000

$ ps -a | grep sleep
23277 pts/2    00:00:00 sleep

$ ./signal.sh 9 23277
Sending SIGKILL signal

$ sleep 1000
Killed

プロセス終了方法については、以前の記事「プロセスをkillする4つの方法」も参考にしてください。

例2:ファイル内のパターンマッチング

この例では、指定したパターンに基づいて、行数や単語数を出力したり、該当する行を削除したりします。

$ cat fileop.sh
#!/bin/bash

# 引数が3つあるか確認 #
if [ $# -lt 3 ]
then
        echo "Usage : $0 option pattern filename"
        exit
fi

# 指定ファイルが存在するか確認 #
if [ ! -f $3 ]
then
        echo "Filename given \"$3\" doesn't exist"
        exit
fi

case "$1" in

# 一致した行数をカウント
-i) echo "Number of lines matches with the pattern $2 :"
    grep -c -i $2 $3
    ;;
# 一致した単語数をカウント
-c) echo "Number of words matches with the pattern $2 :"
    grep -o -i $2 $3 | wc -l
    ;;
# 一致した行をすべて表示
-p) echo "Lines matches with the pattern $2 :"
    grep -i $2 $3
    ;;
# パターンに一致した行をすべて削除
-d) echo "After deleting the lines matches with the pattern $2 :"
    sed -n "/$2/!p" $3
    ;;
*) echo "Invalid option"
   ;;
esac

スクリプトの実行例を示します。まずテスト用ファイルの内容は次の通りです。

$ cat text
Vim is a text editor released by Bram Moolenaar in 1991 for the Amiga computer.
The name "Vim" is an acronym for "Vi IMproved" because Vim was created as an extended version of the vi editor, with many additional features designed to be helpful in editing program source code.
Although Vim was originally released for the Amiga, Vim has since been developed to be cross-platform, supporting many other platforms.
It is the most popular editor amongst Linux Journal readers.

パターン「Vim」に一致する行を削除した結果の出力は以下のようになります。

$ ./fileop.sh  -d Vim text
It is the most popular editor amongst Linux Journal readers.

関連情報として、「Bashの~展開と{ }展開について解説した記事」もぜひ参照してください。

例3:拡張子からファイルタイプを判定

この例では、ファイル名の拡張子に基づいてファイルの種類(テキスト、Cソースなど)を出力します。

$ cat filetype.sh
#!/bin/bash
for filename in $(ls)
do
	# ファイル名から拡張子を取り出す
        ext=${filename##*\.}
        case "$ext" in
        c) echo "$filename : C source file"
           ;;
        o) echo "$filename : Object file"
           ;;
        sh) echo "$filename : Shell script"
            ;;
        txt) echo "$filename : Text file"
             ;;
        *) echo " $filename : Not processed"
           ;;
esac
done

$ ./filetype.sh
a.c : C source file
b.c : C source file
c1.txt : Text file
fileop.sh : Shell script
obj.o : Object file
text : Not processed
t.o : Object file

例4:ユーザーにyes/noを問い合わせる

ソフトウェアのインストール時にライセンス契約の同意を求められる場面のように、ユーザーへyes/noの入力を求めたいことがよくあります。以下のコードスニペットは、その実現方法の一つです。

$ cat yorno.sh
#!/bin/bash

echo -n "Do you agree with this? [yes or no]: "
read yno
case $yno in

        [yY] | [yY][Ee][Ss] )
                echo "Agreed"
                ;;

        [nN] | [n|N][O|o] )
                echo "Not agreed, you can't proceed the installation";
                exit 1
                ;;
        *) echo "Invalid input"
            ;;
esac

$ ./yorno.sh
Do you agree with this? [yes or no]: YES
Agreed

複数のパターンをパイプ記号(|)で区切って並べると、いずれか一つにでも一致すれば、それに関連付けられたステートメントが実行されます。パターンは順番にチェックされ、一致が見つかった時点で評価を終えます。どこにも一致しなければ何も実行されません。

さらに学びたい方は、「Bash配列の15個の実用例」の記事もおすすめです。

例5:起動スクリプト

/etc/init.dディレクトリにある起動スクリプトは、アプリケーションの起動・停止の制御にcase文を使用しています。

case文ではさまざまな種類のパターンを使えますが、プリミティブな値(整数や文字など)をテストする場合には、常にcase文の使用が推奨されます。

$ cat startpcapp
#!/bin/bash

case "$1" in
'start')
echo "Starting application"
/usr/bin/startpc
;;
'stop')
echo "Stopping application"
/usr/bin/stoppc
;;
'restart')
echo "Usage: $0 [start|stop]"
;;
esac

$ ./startpcapp start
Starting application
/usr/bin/startpc started

おすすめの書籍

Bashのcase文を徹底解説!実務で使える5つの実践例Ramesh Natarajan著『Bash 101 Hacks』。私はほとんどの時間をLinux環境で過ごしており、自然とBashコマンドラインとシェルスクリプティングの大ファンになりました。15年前にさまざまな* nix系OSで作業していた頃は、CシェルやKornシェルで多くのコードを書いていました。その後、Linuxシステム管理者として働くようになってからは、可能な限りのタスクをBashシェルスクリプトで自動化しました。そうした経験をもとに、Bashコマンドラインとシェルスクリプティングに関する101の実践例を収録した電子書籍『Bash 101 Hacks』を執筆しました。Bashをマスターしたいと考えているなら、ぜひ本書を読んで、コマンドライン操作とシェルスクリプティングを自在に操れるようになりましょう。

  1. C++における条件分岐の基礎:if-else文とswitch文の使い方を徹底解説

    条件分岐(意思決定)構造では、プログラマーがプログラムに評価・判定させる1つ以上の条件を指定し、その条件が「真(true)」と判定された場合に実行する文、さらに必要に応じて、条件が「偽(false)」と判定された場合に実行する別の文を記述する必要があります。 以下は、多くのプログラミング言語に共通する、典型的な条件分岐構造の一般的な流れを示した図です。 if-else文とは if文の後には、オプションとしてelse文を続けることができます。else文は、ifのブール式が「偽」と判定された場合に実行されます。C++におけるif...else文の基本構文は以下の通りです。 if(boolean

  2. rbashとは?実例でわかる制限付きBashシェルの仕組みと使い方

    Linuxシェルは、GNU/Linux環境における最も強力で魅力的なツールのひとつです。X Window Systemをはじめとするすべてのアプリケーションはシェルを基盤として動作しており、Linuxシェルを使えばシステム全体を精密に制御できます。しかし一方で、コマンドの影響を理解せずに実行してしまうと、システムに深刻な被害をもたらす危険性も秘めています。 特に初心者ユーザーにとって、誤操作によるトラブルは大きなリスクです。そこで役立つのが「制限付きシェル」です。本記事では、rbash(制限付きBash)の概要から、実際に適用される制限内容、有効化の手順、メリット・デメリットまで詳しく解説しま