[bash] コマンドの前で変数への代入をする

2020年6月8日月曜日

bash シェルスクリプト

bashでコマンドの前で変数への代入をする構文を正確に理解してなかったので、整理。

LC_ALL=C sort ...

よく見かけるのはこのパターン。
$ LC_ALL=C sort ...

ソート条件に言語設定が影響してくるのを防ぐのと、パフォーマンス対策で事前にLC_ALLをCにしておく。
manapgeの説明によると、直接影響するのはLC_COLLATEやLC_CTYPEとあるけど、LC_ALLを設定すると他のLC_*系の値より優先される。

i=foo echo $i

同じ様な感じでも、これはうまくいかない。
$ i=foo echo $i


i=fooの代入が実行される前のパース時に$iが先に展開されるからだね。

もうちょっと明示するとこうなる。
$ i=bar
$ i=foo echo $i
bar

fooではなく、barが表示される。

環境変数

manpageを見てみると、こうある。

「単純なコマンドの展開」
変数代入の = の後にあるテキストに対して、チルダ展開、 パラメータ展開、コマンド置換、算術式展開、クォート削除が行われます。 この処理は変数を代入する前に行われます。

コマンド名が残らなかった場合には、 変数を代入した結果が現在のシェル環境に効果を及ぼします。 それ以外の場合、変数は実行されるコマンドの環境に追加されるだけで、 現在のシェル環境には影響を与えません。

なので、環境変数を一時的に変更してコマンドを実行したいけど、以降には影響を与えたくないときにこの構文を使う。
$ cat echo_test.sh
#!/bin/sh
echo $TEST
$ export TEST=foo
$ echo $TEST
foo
$ TEST=bar ./echo_test.sh
bar
$ echo $TEST
foo        # fooのままになってる。

セミコロンを入れると文が切れてしまって、違う意味になるので注意。
$ TEST=bar; ./echo_test.sh
bar
$ echo $TEST
bar        # barに変わってしまう!