bashの変数の展開がいつ行われるのか? あれ、代入済みなのに反映されない?
bashの変数の展開やコマンドの実行の順番の解釈の理解になれば幸いです。
遭遇した問題
$ TEST_A=abc echo $TEST_A
果たして、これは何が出力されるでしょうか?もともとTEST_A
という変数は未定義だったとします。
答え:
$ TEST_A=abc echo $TEST_A
(何も出力されない)
あれ?abcじゃないの?と数人で混乱していました。
なにが起こっていたか
bashのparserが先に変数TEST_A
を展開するため、TEST_A=abc
とは関係なく。何も出力されていませんでした。
そもそもシェルで変数が展開されたあとにコマンドが頭から順番に実行されるため、実質的に
$ TEST_A=abc echo
をしていたわけですね。したがって
$ TEST_B=hoge
$ TEST_B=abc echo $TEST_B
の場合にはhoge
が出力されるわけですが、実質的には
$ TEST_B=hoge
$ TEST_B=abc echo hoge
を実行していたわけです。
確認問題
問題
test.pyを以下の内容で作成します(Python3.6以上)。
import os
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--arg')
args = parser.parse_args()
print(f"{args.arg} {os.environ['TEST_A']}")
このとき、以下を実行するとなにが実行されるでしょうか?
$ TEST_A=foo
$ TEST_A=bar python test.py --arg=$TEST_A
答え
答えを開く
$ TEST_A=bar python test.py $TEST_A
foo bar
解説
arg=$TEST_A
のほうの$TEST_A
はTEST_A=bar
が実行される前にこの1行がすべて展開されるのでfoo
になっています。一方、os.environ['TEST_A']
のほうのTEST_A
は、このコマンドが冒頭から実行されるためTEST_A=bar
が実行されているために、Pythonが実行されるときにはbar
に書き換わっています。この1行を展開されるときには当然test.pyの内容は展開されていないためにこのようなことが起きているようです。
参考
- [How does one properly assign temporary Bash variables on a per-command basis?](https://stackoverflow.com/questions/55912074/how-does-one-properly-assign-temporary-bash-variables-on-a-per-command-basis#:~:text=the[…]20echo%20bar
https://www.gnu.org/software/bash/manual/bash.html#:~:text=%5D-,3.7.1%20Simple%20Command%20Expansion,-When%20a%20simple)