
こんにちは、masm11 です。
みなさんは、シェルスクリプトを書きますか? 私はよく書きます。 シェルスクリプトを書いてるとよく出てくる文法が、
if [ "$foo" = "bar" ]; then
です。[ と ] です。今回はこれについて取り上げます。
なお、= とか -ne とか -f とか -x とか、いろいろな機能がありますが、
今回はそういう一般的な使い方の話をするつもりはありません。
[ はコマンド
if の文法は、
if コマンド; then
です。コマンドを実行し、成功 (exit status が 0) の場合は then 以降が実行されます。
なので、[ はコマンドとして実装されています。
最初に例として挙げた
if [ "$foo" = "bar" ]; then
は、[ コマンドに
$fooのシェル変数を展開したもの=bar]
が渡されています。
test コマンドとは
一方で、test というコマンドもあります。
使い方は以下のようになります。
if test "$foo" = "bar"; then
つまり、[ を test に置き換え、] を省きます。
それだけです。
[ と test の違い
では、[ と test の違いは何でしょうか?
違いはほとんどありません。これは、昔の UNIX OS では
[ は test へのシンボリックリンクになっていたことからも
判るとおりです (最近の OS ではシェルの built-in なことも多いです)。
UNIX では、自分がどんな名前で実行されたかを各コマンドが知ることができます。
C では main 関数を以下のように書きます。
int main(int argc, char **argv)
argv[0] を見ればどんなコマンド名で実行されたかが判ります。
また、Ruby では $0 に入っていますし、
Python では sys.argv[0] に入っています。
そして、いくつかのコマンドはコマンド名によって動作を変えます。
test コマンドもその一つで、
[として実行された場合には、最後の引数が]でなければエラーとする
という仕様です。エラーメッセージは以下のとおりです。
[: missing ']'
test と [ の違いはそれだけです。
もし、手元で試して、エラーメッセージが
[: ']' expected
だった場合、それは bash の built-in です。bash で外部コマンドの [ を
実行するには、以下のようにします。
LANG=C command [
[ を使う際の注意
[ を使う場合には、一つ注意があります。先ほど以下のように書きました。
[として実行された時には、最後の引数が]でなければエラーとする
「最後の引数が」です。つまり、
if [ "$foo" = "bar"]; then
だと動かないんですね。この場合、[ コマンドに渡されるのは、
$fooのシェル変数を展開したもの=bar]
なので、最後の引数が bar] であって ] ではないからです。
まとめ
…知ってましたよ? ただちょっとミスって本番での最終テストで期待通りの 結果にならなかっただけです (泣)