web-dev-qa-db-ja.com

このシェル/バッシュ構文は何ですか:someVariable = someValue someCommand

同僚の1人が、慣れていないBash構文を提供してくれました。私のGoogle fooは、それが何をするのか、なぜ/いつそれを使用する必要があるのか​​を理解するのに失敗しました。

彼が私に送ったコマンドは次の形式でした:

someVariable=something command

最初は、これは以下と同等であると思いました。

someVariable=something ; command

または

someVariable=something 
command

しかし、これはケースに表示されません。例:

[Jan-03 11:26][~]$ # Look at the environment variable BAZ. It is currently empty
[Jan-03 11:26][~]$ echo $BAZ

[Jan-03 11:27][~]$ # Try running a command of the same format    
[Jan-03 11:27][~]$ BAZ=jake echo $BAZ

[Jan-03 11:27][~]$    
[Jan-03 11:27][~]$ # Now, echo BAZ again. It is still empty:    
[Jan-03 11:27][~]$ echo $BAZ

[Jan-03 11:27][~]$    
[Jan-03 11:28][~]$    
[Jan-03 11:28][~]$ # If we add a semi-colon to the command, we get dramatically different results:
[Jan-03 11:28][~]$ BAZ=jake ; echo $BAZ
jake
[Jan-03 11:28][~]$
[Jan-03 11:28][~]$ # And we can see that the variable is actually set:
[Jan-03 11:29][~]$ echo $BAZ
jake
[Jan-03 11:29][~]$

この構文は何をしますか?設定された変数はどうなりますか?なぜこれが機能するのですか?

27

これは次と同等です。

( export someVariable=something; command )

これにより、someVariableは、割り当てられた値を持つ環境変数になりますが、実行されるコマンドに対してのみです。

bashマニュアルの関連部分は次のとおりです。

シンプルなコマンド

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

(...)

シンプルなコマンド拡張

[コマンド展開から]コマンド名が得られない場合、変数の割り当ては現在のシェル環境に影響します。それ以外の場合、変数は実行されたコマンドの環境に追加され、現在のシェル環境に影響を与えません

注:これはbashに固有のものではなく、 POSIXで指定 であることに注意してください。


編集-回答のコメントから要約されたディスカッション

理由 BAZ=JAKE echo $BAZ、JAKEを出力しないのは、変数置換が何よりも先に行われるためです。変数置換をバイパスすると、これは期待どおりに動作します。

$ echo_baz() { echo "[$BAZ]"; }
$ BAZ=Jake echo_baz
[Jake]
$ echo_baz
[]
39
xhienne

これらは シンプルコマンド のコンテキストでの変数割り当てです。 xhienne で述べたように、外部コマンドの場合、コマンドの実行中に割り当てられた値をエクスポートすることと同じです。

例では組み込みコマンドを使用しているため、動作はまったく異なります。割り当ては現在の環境に影響しますが、組み込みコマンドの実行後に効果が持続するかどうかは指定されていません。例を理解するには、変数が処理される前にパラメーターの展開が行われることを知っておく必要があります。したがって

 BAZ=jake echo $BAZ

シェルは最初に$BAZを展開し(結果は何もない)、次にBAZjakeに設定し、最後に実行します

 echo

空の行を出力します。 (その後、シェルは、後続のecho $BAZが示すようにBAZを忘れます。)

 BAZ=jake; echo $BAZ

は2つのコマンドとして解釈されます。最初にBAZ変数が現在の環境で設定され、次にecho $BAZecho jakeに展開されて実行されます。

17
Stephen Kitt

ここで発生する重要なことがいくつかあります。

  • bashリファレンスマニュアル 、簡単なコマンド拡張、セクション「コマンド名が生成されない場合、変数の割り当ては現在のシェル環境に影響します。それ以外の場合は、変数が追加されます。実行されたコマンドの環境に、現在のシェル環境には影響しません。」したがって、var="something" command arg1 arg2と言うと、コマンドはvarがコマンドの環境にあり、commandが終了すると消えて実行されます。これのデモは簡単です。コマンド内からコマンドの環境にアクセスします。

    $ BAZ="jake" python -c "import os; print os.environ['BAZ']"                                                              
    jake
    

    これは驚くべきことではありません。このような構文は、環境が変更されたプログラムを実行するために頻繁に使用されます。私の仲間のunix.stackexchange.comとaskubuntu.comのユーザーは、この例を認識します。ユーザーがドイツ語のロケールを使用していて、英語のみで話す場合は、発生している問題を再現し、次のように英語で出力を取得するように依頼できます。

    LC_ALL=C command
    

    また、環境アクセスはpythonに固有のものではないことにも注意してください。 Cまたはその他のプログラミング言語を使用して実行できます。それはたまたまたまたま私の「選択した武器」であり、このデモでのみ使用されました。

  • 変数の展開は、何かが実行される前に行われます。したがって、BAZ="foo" echo $BAZのようなものを実行すると、シェルは最初にその環境を調べ、そこで変数BAZを検出しないため、$BAZを空のままにします。その簡単なデモンストレーションは次のとおりです。

    $ BAZ="jake" python -c "import sys; print 'ARG:',sys.argv[1]" $BAZ                                                       
    ARG:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    IndexError: list index out of range
    

また、2つの別個のコマンドステートメントであるBAZ=jake; echo $BAZとの違いも重要です。ここで、BAZ=jakeはシェルの環境に残ります。ユースケースはあなたの意図に依存します。そのような変数を必要とする複数のプログラムを実行する場合は、そのような変数をexportすることが望ましい場合があります。この1つの特定の時間だけ必要な場合は、先行する変数の割り当てが望ましい場合があります。

5

簡単な言葉で:

BAZ=jake echo $BAZ

variable substitutionはコマンドの最初に行われるため、何も出力されません。つまり、このコマンドラインで最初に発生するのは$BAZで、変数BAZが定義されている実際の値(存在する場合)に置き換えられます。これは、シェルが同じコマンドラインでBAZ=jakeを考慮する前でも起こります。

コマンドの実行前は、BAZには値が割り当てられておらず、BAZ=jake$BAZが解決された後にのみ考慮されるため、$BAZは解決されません任意の値。したがって、echo $BAZは何も出力しません。

BAZ=jakeは指定されたコマンドの一部にすぎません(シェルはそれを環境変数と見なしたり設定したりしません)。これは、同じコマンドラインの一部として実行されるプロセスがこの変数BAZを使用する場合に、ほとんど役に立ちます。コマンドの実行が完了すると、BAZjakeの値は揮発性になります。

例:]# LD_LIBRARY_PATH="new_path" ldconfig、ここでldconfigコマンドは内部的に変数LD_LIBRARY_PATHを参照し、このコマンドラインには変数の展開はありません上記とは異なり。

その他の場合:

BAZ=jake; echo $BAZ  

これらは、1行で示される2つの異なるコマンドです。次々と実行するのと同じくらい良いです。

3
VanagaS