条件によって処理内容を変えたり、繰り返しなどを行ったりする際の書き方を「制御構文」と呼びます。代表的な制御構文としては、if文、case文、for文、while文があります。今回取り上げるのは、条件によって処理を分岐させる「if」です。
「もし○○だったら、××する」のように、ある条件のときだけ何かをする、という処理を書きたい場合に「if」を使用します。ifを使って条件分岐を行う文(条件文)は「if文」とも呼ばれます。
条件の部分は、通常「ある値が××と一致する」や「値が××より大きい(小さい)」などで示されます。これを「条件式」と呼びます。“値”には、例えば変数や引数の内容、文字列の長さ、計算結果、別のコマンドの実行結果などを使います。
ifはコマンドラインでも使用できます。詳細については、連載『Linux基本コマンドTips』の第223回を参考にしてください。
if文は「if 条件 then ~ fi」のように、「if」から始まり「fi」で終わります。“それ以外”という場合には「else」を、別の条件を使いたい場合は「elif」を使います。
- if 条件
- then
- 条件が成立したとき実行するコマンド
- fi
- if 条件
- then
- 条件が成立したとき実行するコマンド
- else
- 条件が成立しなかったとき実行するコマンド
- fi
- if 条件1
- then
- 条件1が成立したとき実行するコマンド
- elif 条件2
- then
- 条件1が成立せず、条件2が成立したときに実行するコマンド
- elif 条件3
- then
- 条件1、条件2が成立せず、条件3が成立したときに実行するコマンド
- else
- 全ての条件が成立しなかったとき実行するコマンド
- fi
【※】「elif」のブロックは幾つあっても構いません。
- if 条件1 && 条件2
- then
- 条件1と条件2の両方が成立したときに実行するコマンド
- else
- それ以外のときに実行するコマンド
- fi
【※】「elif」でも同様に書くことができます。
- if 条件1 || 条件2
- then
- 条件1と条件2のいずれかが成立したときに実行するコマンド
- else
- それ以外のとき(=条件1、条件2ともに成立しなかった場合)に実行するコマンド
- fi
【※】「elif」でも同様に書くことができます。
なお、“あるコマンドの実行に成功したら~”や、“失敗したら~”という判定の場合は、ifを使わず、「&&」と「||」のみでコンパクトに書くこともできます。
- コマンドA && コマンドAが成功したとき実行するコマンド
- コマンドA || コマンドAが失敗したとき実行するコマンド
「if」と「elif」の使い方を簡単に試してみましょう。以下は、引数が1つだったら「one」、2つなら「two」、3つなら「three」、それ以外なら「ELSE」と表示するというスクリプトです。
- #! /bin/bash
- if [ $# = 1 ]
- then
- echo "one"
- elif [ $# = 2 ]
- then
- echo "two"
- elif [ $# = 3 ]
- then
- echo "three"
- else
- echo "ELSE"
- fi
【※】引用符を付けて「if [ "$#" = "1" ]」のように書くこともできます。
- $ chmod +x eliftest
- $ ./eliftest
- ELSE #← 引数がないので「ELSE」と表示された
- $ ./eliftest aaa bbb
- two #← 引数が2つなので「two」と表示された
if文の場合、「then」と「else」のブロックの最後は改行する必要があります。改行したくない場合は「;」記号を使用します。例えば、thenだけの行があると縦に長くなってしまうので、「;」記号で区切ると読みやすくなります。
thenやelseのブロックで複数のコマンドを実行する場合も、改行または「;」で区切ります。この方法で、本連載第25回で作成した「grepall」スクリプトを書き換えると、以下のようになります。
- #! /bin/bash
- if [ -n "$1" ]; then
- ptn="$1"
- else
- echo "USAGE: `basename $0` pattern [file] [dir]"
- exit
- fi
- if [ -n "$2" ]; then
- file="$2"
- else
- file="*"
- fi
- if [ -n "$3" ]; then
- dir="$3"
- else
- dir="."
- fi
- grep -Hn -e "$ptn" -r --include="$file" "$dir"
少々極端な例ですが、それぞれのif文を1行にすると以下のようになります。読みやすさと、後で処理を変更する際の編集しやすさを考えて調整しましょう。
- #! /bin/bash
- if [ -n "$1" ]; then ptn="$1"; else echo "USAGE: `basename $0` pattern [file] [dir]"; exit; fi
- if [ -n "$2" ]; then file="$2"; else file="*"; fi
- if [ -n "$3" ]; then dir="$3"; else dir="."; fi
- grep -Hn -e "$ptn" -r --include="$file" "$dir"
if文の中にif文を書くことがあります。これを“if文の「ネスト」(nest:入れ子)”と表現することがあります。
先ほどのgrepallスクリプトを、if文で引数の数を見ながら処理をするように書き換えてみましょう。スクリプト名は「grepall2」とします。
- #! /bin/bash
- if [ $# -ge 1 ]; then
- ptn=$1
- file="*"
- dir="."
- if [ $# -ge 2 ]; then
- file="$2"
- if [ $# -ge 3 ]; then
- dir="$3"
- fi
- fi
- grep -Hn -e "$ptn" -r --include="$file" "$dir"
- else
- echo "USAGE: `basename $0` pattern [file] [dir]"
- fi
“if文の中にif文”のように、あるブロック(ひとまとまり)の中に別のブロックを入れるような場合は、内側のブロックの先頭に空白を入れると読みやすくなります。これを“インデント”と呼びます。
シェルスクリプトでは、「空白を入れてよい場所には幾つ入れてもよい」「行頭に空白を入れてもよい」というルールがあるため、このように書くことができます。ただし、処理はあくまでもifからfiまでが1つのブロックとなりますので、インデントを間違えてしまうと逆にとても読みにくいスクリプトになってしまうので注意しましょう。
“引数の個数が1以上”という条件は、「[ $# -ge 1 ]」と表現できます。「ge」は「greater or equal」の略です。[ ]の前後も含め、それぞれの空白は必須です。
条件の書き方についてはこの後の回で取り上げます。連載『Linux基本コマンドTips』の「test」コマンド(基礎編、応用編)も参考にしてください。
西村 めぐみ(にしむら めぐみ)
PC-9801NからのDOSユーザー。PC-486DX時代にDOS版UNIX-like toolsを経てLinuxへ。1992年より生産管理のパッケージソフトウェアの開発およびサポート業務を担当。著書に『図解でわかるLinux』『らぶらぶLinuxシリーズ』『Accessではじめるデータベース超入門[改訂2版]』『macOSコマンド入門』など。2011年より、地方自治体の在宅就業支援事業にてPC基礎およびMicrosoft Office関連の教材作成およびeラーニング指導を担当。
Copyright © ITmedia, Inc. All Rights Reserved.
Linux & OSS 記事ランキング