こんにちは、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]
であって ]
ではないからです。
まとめ
…知ってましたよ? ただちょっとミスって本番での最終テストで期待通りの 結果にならなかっただけです (泣)