コマンドTips

読めばだんだんコマンドに見えてくる[の話

シェルスクリプトを読んでいるとしばしば次のようなif制御構文が出てくる。

if [ "_$ans" = "_ABC" ] ; then
	ans=CDE
fi

このソースコードの中にコマンドは何個あるか、という問に対してきっぱり回答できる方は少ないかもしれない。ifはコマンドなのか、thenはどうか、となってしまう。実はここでのコマンドは[だ。一見するとif制御構文専用の括弧に見えるかもしれないが、[がコマンドである。

シェル(/bin/sh)のif制御構文はコマンドの返す値で条件分岐を実施する。たとえば次のように振る舞う。

if grep keyword target_file > /dev/null ; then
	echo "ありました。"
else
	echo "ありません。"
fi

grep(1)は検索語が見つかると最後に返り値として0を返す。0は成功を意味する。if制御構文はその値によって振る舞いを変える。つまり、検索語が見つかれば「echo "ありました。"」を実行し、見つからなければ「echo "ありません。"」を実行する。シェルのif制御構文にはC言語などに見られるような括弧は存在しない。

次の記述方法にも括弧が存在しない。

if test 1 -eq 1 ; then
	echo "1は1"
else
	echo "1は1でない(そんなわけない)"
fi

この例では、test(1)というコマンドに「整数として1と1は等しいかどうか」を判断させている。test(1)はコマンドなので、testの後ろの1、-eq、1はtest(1)コマンドの引数(オプション)ということになる。以上を踏まえて、次のif制御構文を見てみよう。

if [ 1 -eq 1 ] ; then
	echo "1は1"
else
	echo "1は1でない(そんなわけない)"
fi

これはtestを別の書き方で書いたものだ。test(1)コマンドのかわりに、ちょっと奇妙な感じがするかもしれないが[(1)コマンドを使って書き直したものにすぎない。[(1)コマンドは引数の最後に]を必要とするので、引数の最後に]を付け加えてある。あとはtestと同じだ。

まとめると次のようになる。

シェルスクリプトビギナーはif [ ] のどこに空白を入れて良いか分からず、うまくスクリプトが動作しなくてシェルスクリプト嫌いになることがある。ここで説明したことを理解しておけばもう大丈夫だろう。

if制御構文の記述方法に慣れてくると、if制御構文の代わりに次のような書き方をすることもある。

[ "_$A" = "_" ] && exit 1

これは左のコマンドがうまくいったら右のコマンドを実行するという意味である。つまり、次のコードと同じということになる。

test "_$A" = "_" && exit 1

こっちの方がコマンドっぽくなるが、ちょっと見難いかもしれない。慣れの問題ではあるが、[ "_$A" ...の書き方の方が目に馴染んでくるので不思議なものだ。

last modified: 2014-01-13 16:01:13