Bashの予期しない動作


7

からman bash

単純なコマンドは、一連のオプションの変数割り当てです
空白で区切られた単語とリダイレクトが続く
制御オペレーターによって終了されました。最初の単語は
実行されるコマンド。引数ゼロとして渡されます。の
残りの単語は引数として呼び出されたコマンドに渡されます。

したがって、次のように記述することは完全に合法です。

foo=bar echo $foo

しかし、期待どおりには動作しません(改行のみが出力されます)。私にとっては非常に奇妙です:

$ foo=bar printenv
foo=bar
TERM=rxvt-unicode
[...]

誰かが私が間違っているところを教えてもらえますか?

回答:


6

これは、コマンドが実行される前に変数の展開が行われるために発生します。変数の展開が発生した時点でfoo設定されていないため、空の文字列に展開されます。その後、コマンドが実行され、が設定されますfoo


1
また、fooはechoコマンドのプレフィックスとして設定されているため、そのコマンドに対してのみ設定されることに注意してください(後続のコマンドに対しては設定されません)。と比較しますfoo=bar eval 'echo eval sees $foo'; echo echo sees $foo(ここで$fooは、evalコマンド内で展開されているため、値そこで置換されます、次のエコーコマンドでは置換されません)。
ゴードンデイヴィソン

1
これは、子供の環境(つまりecho、元の質問またはevalゴードンの例)の課題です。子の環境での変数の割り当ては、親の変数の値には影響しません。foo=bar eval 'foo=$foo'; echo $foo改行のみを出力します。
デニスウィリアムソン

From man bash:「コマンド名が発生しない場合、変数の割り当ては現在のシェル環境に影響します。そうでない場合、変数は実行されたコマンドの環境に追加され、現在のシェル環境には影響しません。読み取り専用変数にエラーが発生すると、コマンドはゼロ以外のステータスで終了します。」
デニスウィリアムソン

1

あなたがやっているfoo=barecho $foo1行で、それは動作しません。次の3つのいずれかを行う必要があります。

  1. それらを個別のコマンドとして実行します。すなわち:foo=bar Enter echo $foo

  2. それらを1行で実行しますが、2つの間にセミコロンを入れます。すなわち:foo=bar; echo $foo

  3. #2と同じですが、二重アンパサンドを使用します。すなわち:foo=bar && echo $foo

2と3の違いは、3は成功したecho $foo場合にのみ実行されるfoo=barことです。


感謝しますが、私は問題を回避する方法を知っています。私が提供した例にのみ興味がありました。
cYrus

+1:代わりの素晴らしいセット。これは誰かにとって便利かもしれません。
cYrus


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.