シェルスクリプトに挑戦しよう(7)制御構文[その1]――ifによる条件分岐“応用力”をつけるためのLinux再入門(27)

条件によって処理内容を変えたり、繰り返しなどを行ったりする際の書き方を「制御構文」と呼びます。代表的な制御構文としては、if文、case文、for文、while文があります。今回取り上げるのは、条件によって処理を分岐させる「if」です。

» 2018年10月24日 05時00分 公開
[西村めぐみ@IT]
「“応用力”をつけるためのLinux再入門」のインデックス

“応用力”をつけるためのLinux再入門

「if」はどんなときに使用するのか?

 「もし○○だったら、××する」のように、ある条件のときだけ何かをする、という処理を書きたい場合に「if」を使用します。ifを使って条件分岐を行う文(条件文)は「if文」とも呼ばれます。

 条件の部分は、通常「ある値が××と一致する」や「値が××より大きい(小さい)」などで示されます。これを「条件式」と呼びます。“値”には、例えば変数や引数の内容、文字列の長さ、計算結果、別のコマンドの実行結果などを使います。

 ifはコマンドラインでも使用できます。詳細については、連載『Linux基本コマンドTips』の第223回を参考にしてください。

●ifの基礎構文

 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
▲複数の条件を組み合わせる場合(1)ANDの関係

【※】「elif」でも同様に書くことができます。


if 条件1 || 条件2
then
  条件1と条件2のいずれかが成立したときに実行するコマンド
 else
  それ以外のとき(=条件1、条件2ともに成立しなかった場合)に実行するコマンド
fi
▲複数の条件を組み合わせる場合(2)ORの関係

【※】「elif」でも同様に書くことができます。



 なお、“あるコマンドの実行に成功したら〜”や、“失敗したら〜”という判定の場合は、ifを使わず、「&&」と「||」のみでコンパクトに書くこともできます。

コマンドA && コマンドAが成功したとき実行するコマンド
▲&&演算子による書き方
コマンドA || コマンドAが失敗したとき実行するコマンド
▲||演算子による書き方

●ifとelifを試してみる

 「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とelifの練習用スクリプト(eliftest)

【※】引用符を付けて「if [ "$#" = "1" ]」のように書くこともできます。


$ chmod +x eliftest
$ ./eliftest
ELSE		#←  引数がないので「ELSE」と表示された
$ ./eliftest aaa bbb
two		#←  引数が2つなので「two」と表示された
▲実行結果(eliftest)

●if文の改行ルール

 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"
▲「;」記号でthenの前の改行をなくす(第25回の「grepall」を加工)

 少々極端な例ですが、それぞれの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文を1行にした(grepallを加工)

条件文の中に条件文を書く(if文のネスト)

 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文のネスト(grepall2)

 “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.

スポンサーからのお知らせPR

注目のテーマ

4AI by @IT - AIを作り、動かし、守り、生かす
Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。