bashの変数代入の=の前後にスペースを入れてはいけない理由

bashクックブック

bashクックブック

bashクックブックを読んでいる。5章の冒頭でbashの変数代入の構文について触れられている。

bashで変数に値を代入する時は、name=valueのように'='の前後にスペースを入れずに書かなくてはならない。はっきり言って分かりにくい。「変数代入のつもりがスペースが入っていてうまく動かない(しかもそれに気がつかない)」なんてbashスクリプトを始めたら一度はハマるポイントだと思う。

大抵の言語では'='の前後にスペースを入れても良いし、普通はそうする。例えばpythonでは次のように書く(対話モードの例)。

$ python
>>> answer = 42
>>> print answer
42

なんでbashはこれができないんだろうか。その理由がbashクックブックに書いてあった。

例えば、echoという名前の変数に値を代入したい場合、以下のように書く*1

$ echo=42
$ echo $echo
42

この'='の前後にスペースを足すと、

$ echo = 42
= 42

echoというコマンドを、引数を2つ指定して実行したことになってしまう。つまり、'='を引数として指定できるようにするために、'='の前後にスペースがなければ代入文、スペースがあれば'='は引数と解釈しているのだ。

そのすぐ後には、変数を参照するときは変数名の前に$をつける理由が書いてある。

例えばpythonでは、""で囲まず単に変数名を書けばその値を参照する。

# さっきと同じ例
>>> answer = 42
>>> print answer
42

そして、""で囲めば文字列になる。

>>> print "answer"
answer

一方bashでは、""で囲まずに変数名を書いても(""で囲んだのと同じように)文字列になる。

$ echo answer
answer

このままでは変数の値を参照できなくなるので、参照したいときは「変数名の前に$をつける」という方法を使う。

$ answer=42
$ echo $answer
42

両者の違いは、「主にスクリプトとして書いて使用する」か「主に対話的に使用するか」という利用シーンの差からくると思う。

pythonのようなプログラム言語ではコード上に直接""で文字列を書くことはあんまりなくて、変数値を参照したいことの方が多い。なので値参照が楽なように単なる変数名だけでできるようになっている。

でもbashでは変数値を参照することは少なくて、ほとんど文字列を直接引数として指定することになる。そこで""で囲まなくても文字列として扱うようになっているわけだ。その代わり変数値参照に$が必要になるが、対話モードではあんまり使わないので問題ない。

言われてみれば当たり前のことだが、このクックブックを読むまでは考えたことがなかった。この例に限らず、単に問題の答えを載せるだけではなく、その裏側の理論までさりげなく解説してある。この前は「たいしたことない」とか偉そうなことを言ってしまったが、読み進めてみるとなかなかいい本だ。ちゃんと読もう。

*1:先頭の$はbashのプロンプトだ。念のため。