シェルでは制御構造コマンドとして、条件分岐文として「if」「case」が利用できます。シェルスクリプトを習得する上で非常に重要な制御文なので、この機会にマスターしましょう。
この記事でわかること
- 条件分岐とは?
- if文とは?
- case文とは?
条件分岐とは?
条件分岐とは、「Aという条件を満たした場合に繰り返し処理を実行し、Bという条件になったら処理を辞める」といった条件式を指しています。中でも「if文」と「case文」は、よく用いられる条件分岐構文になります。
if文とは?
if文は実行結果「真(true)」「偽(false)」によって分岐する構文です。例えば、「文字列Aと文字列Bは一致しているか?」といった考え方です。「if」文は、ほとんどの場合「test」コマンドと組み合わせて用いられます。
また、多少処理的に複雑になりますが、「ネスト(入れ子)」構造にすることも可能です。
「if-elif-else」文
条件分岐を複数に分けたい場合は「if-elif-else」文で制御します。「elif」は、単純に条件の数分指定可能です。「それ以外(すべてに該当しない場合)」の条件分岐を指定するには「else」を用います。
上記のイメージを元にした書式を下記に記述します。
コマンドの書式
if [ 条件式 ]; then
アクション1
elif [ 条件式 ]; then
アクション2
else
アクション3
fi
実際に「if」文を実行してみます。ここでは、引数に指定した"test.txt"の属性が、「ファイルなのか」「ディレクトリなのか」、もしくはどちらでもない「オブジェクトなのか」を判定するシェルスクリプトを作成してみます。
下記のロジックをコンソールへ入力してみましょう。
# 予め"test.txt"ファイルを作成しておく
touch test.txt
str1="これはファイルです。"
str2="これはディレクトリです。"
str3="不明なオブジェクトです。判定できません。"
judge_type (){
var=${1}
if [ -f ${var} ]; then
echo " [${var}] : ${str1}"
elif [ -d ${var} ]; then
echo " [${var}] : ${str2}"
else
echo " [${var}] : ${str3}"
fi
}
下記は実行結果です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[root@CentOS7 bin]# str1="これはファイルです。" [root@CentOS7 bin]# str2="これはディレクトリです。" [root@CentOS7 bin]# str3="不明なオブジェクトです。判定できません。" ----------------------------------------------------------- [root@CentOS7 bin]# judge_type (){ > var=${1} > if [ -f ${var} ]; then > echo " [${var}] : ${str1}" > elif [ -d ${var} ]; then > echo " [${var}] : ${str2}" > else > echo " [${var}] : ${str3}" > fi > } ----------------------------------------------------------- [root@CentOS7 bin]# judge_type "test.txt" [test.txt] : これはファイルです。 |
引数で指定した"test.txt"の属性は、ファイルであることが分かりました。
以降で説明する「if-else」文も「if」文も考え方は全く同じです。分岐するアクションの数が異なるだけです。
「if-else」文
単純に2者択一等の「真(true)」「偽(false)」比較の場合には、「if-else」文を使用します。
書式は、下記の様になります。下記の書式では、[ ]の中の条件式の結果が真となる場合にアクション1を実行し、それ以外の場合はアクション2を実行します。
コマンドの書式
if [ 条件式 ]; then
アクション1
else
アクション2
fi
「if」
単に「真(true)」の時のみの判定も可能です。
上記イメージの判定は、「真(true)」の時のみ、アクション1を実行します。それ以外はスルーします。
コマンドの書式
if [ 条件式 ]; then
アクション1
fi
case文とは?
case文は1つの変数だけで複数の条件分岐を設定出来るのが特徴です。変数の値がパターン条件にマッチした時にマッチした条件の処理を実行します。
ちなみに、いくつか注意点がありますので下記のリストにまとめてみました。
- 処理の終了には「;;」を記述すること。
- case文の終わりにはesacと記述すること。
- 変数が全ての条件式にマッチしなかったときはなにも処理されません。
注意点に挙げるほどではないですが、複数の処理をさせたい場合は改行をすることで後で読み返したときに可読性が高くなります。
コマンドの書式
case 値 in
パターン条件1) 処理1 ;;
パターン条件2) 処理2 ;;
パターン条件3) 処理3 ;;
esac
「Case」文も「if」文同様に、「ネスト(入れ子)」構造にすることが可能です。
キーボード入力を受け付けるロジックになるため、少し実践的に「シェルスクリプト」ファイルとして作成します。判定には「Case」文を使用します。
これから作成する「シェルスクリプト」は、キーボードから入力された引数が「アルファベット」「数値」「それ以外」のいずれかに該当するモノかを判定するロジックです。
str1="入力されたのはアルファベットですね。"
str2="入力されたのは数字ですね。"
str3="入力された文字は不明な文字種です。"
read -p "文字を入力してください。:" input
case "${ input }" in
[a-zA-Z] ) echo "${ str1 }" ;; 👈(※1)
[0-9] ) echo "${ str2 }" ;; 👈(※2)
* ) echo "${ str3 }" ;; 👈(※3)
esac
※1:[a-zA-Z]は、変数の値がアルファベットの小文字と大文字のときにマッチします。
※2:[0 - 9]は、変数の値が数字の0~9のときにマッチします。
※3:*は、すべての文字列にマッチします。
パターン条件に記述可能なワイルドカードは、以下の意味を持ちます。
* :文字列全部(文字がなくても)に合致する
? :1文字に合致する
[...] :[ ]の中に含まれる文字のどれか1つ
[!...] :[ ]に含まれない文字に合致する
複数の条件を指定することも可能です。
ちなみに、下記のコマンドでプロンプトからの引数入力を要求します。
# プロンプトからの引数入力を要求
read -p "文字を入力してください。:" input
Case分に対応した記述例)
[ <BASE_DIR>/case_pattern.sh ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
#!/bin/sh #_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ # # ver.1.0.0 yyyy.mm.dd # # Usage: # sh <BASE_DIR>/case_pattern.sh # # Description: # Case文を使ってマッチした条件の値を出力する。 # # 設計書 # なし # #_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ # ---------------------------------------------------------- # variables (変数の宣言領域) # ---------------------------------------------------------- scope="var" rc=2 str1="入力されたのはアルファベットですね。" str2="入力されたのは数字ですね。" str3="入力された文字は不明な文字種です。" # ---------------------------------------------------------- # functions (関数を記述する領域) # ---------------------------------------------------------- scope="func" # -------------------------------------------------- # devider. # -------------------------------------------------- # return N/A # -------------------------------------------------- line (){ echo -e "\\n ------------" echo -e " ▼ ${1}" } # ---------------------------------------------------------- # pre-process (事前処理ロジックを記述する領域) # ---------------------------------------------------------- scope="pre" # ---------------------------------------------------------- # main-process (メインロジックを記述する領域) # ---------------------------------------------------------- scope="main" read -p "文字を入力してください。:" input case "${input}" in [a-zA-Z]) echo "${str1}" ;; [0-9] ) echo "${str2}" ;; * ) echo "${str3}" ;; esac if [ $? -eq 0 ]; then rc=0 fi # ---------------------------------------------------------- # post-process (事後処理ロジックを記述する領域) # ---------------------------------------------------------- scope="post" exit $rc |
Case分に対応した実行例)
1 2 3 4 5 6 7 8 9 10 11 |
[root@CentOS7 bin]# sh case_pattern.sh 文字を入力してください。:a 入力されたのはアルファベットですね。 ----------------------------------------------------------- [root@CentOS7 bin]# sh case_pattern.sh 文字を入力してください。:1 入力されたのは数字ですね。 ----------------------------------------------------------- [root@CentOS7 bin]# sh case_pattern.sh 文字を入力してください。:% 入力された文字は不明な文字種です。 |
さらに詳しく
- *(ワイルドカード)のみを条件とした場合は全ての文字列をマッチします。
*は、すべての文字列にマッチします。
abc*:「abc」で始まるすべての文字列にマッチします。
a*bc :「a」ではじまり「bc」で終わる文字列すべてにマッチします。 - [ - ]で設定した範囲の文字や数字にマッチします。
具体的には下記のように範囲指定をしていします。
[a - z]:変数の値が小文字のアルファベット「a~z」のときにマッチします。
[A - Z]:変数の値が大文字のアルファベット「A~Z」のときにマッチします
[a-zA-Z]は、変数の値がアルファベットの小文字と大文字のときにマッチします。
[0 - 9]は、変数の値が数字の0~9のときにマッチします。 - OR条件
a || A):変数の値がaまたはAの時にマッチします。
「 |(パイプ)」は「or (または)」の意味で、パターンの一番最後には「何も合致しなかった場合」という意味で「 * ) 」とするのが一般的です。
「*(アスタリスク)」は「すべてに合致する」という意味の特殊文字なので、上から順番にパターンを比較していき、すべてに合致しなかった場合、必ず一番最後の「*(アスタリスク)」でキャッチされ、処理を実行することになります。
Shellスクリプト基礎知識(全11記事+1)
├─シェルスクリプトの基本事項!
├─変数と特殊変数について!
├─演算子「算術演算子」「比較演算子」について!
├─条件分岐「if」「case」について!
├─ループ処理「for」「while」について!
├─文字列置換「bash」「sed」について!
├─複数行のテキスト出力!ヒアドキュメントについて!
├─書式?戻り値?シェルスクリプト内の関数について!
├─シェルの組み込みコマンドについて!
├─クォートとは?コマンド置換とは?実現方法と内容の違いについて!
└─リダイレクトとは?標準入力・出力、標準エラー出力等について!
(補足)シェルスクリプトの設計書とは?必要な項目や書き方等を解説!