このシェル/ Bashの構文は何ですか:someVariable = someValue someCommand [重複]

このシェル/ Bashの構文は何ですか:someVariable = someValue someCommand [重複]

私の同僚が私に慣れていない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][~]$

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

答え1

これは次のとおりです。

( export someVariable=something; command )

someVariableこれにより、指定された値を使用して環境変数が生成されますが、実行中のコマンドに対してのみ生成されます。

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

簡単なコマンド

簡単なコマンドは順序ですオプションの変数割り当てスペースで区切られた単語とリダイレクトが続き、制御演算子で終了します。最初の単語は実行するコマンドを指定し、引数0に渡されます。残りの単語は、呼び出されたコマンドに引数として渡されます。

(...)

簡単なコマンド拡張

[コマンド拡張] このコマンド名を生成しない場合、変数の割り当ては現在のシェル環境に影響します。そうでなければ、コマンドが実行される環境に変数が追加され、現在のシェル環境には影響しません。

注:これは限定されませbashんが、POSIXで指定


編集 - 回答のコメントでの議論のまとめ

BAZ=JAKE echo $BAZJAKEが印刷されない理由は、変数置換が他のものよりも先に行われるためです。変数置換をバイパスすると、期待どおりに機能します。

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

答え2

これは状況に応じた変数の割り当てです。簡単なコマンド。 〜のようにシアン外部コマンドの場合、コマンドの実行中に割り当てられた値をエクスポートするのと同じです。

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

 BAZ=jake echo $BAZ

シェルは最初に展開され$BAZ(結果なしで)BAZに設定され、jake最後に実行されます。

 echo

空白行を印刷します。 (後で示すBAZように、シェルは忘れてしまいますecho $BAZ。)

 BAZ=jake; echo $BAZ

2つのコマンドとして解釈されます。まず、BAZ現在の環境で変数を設定してから展開しecho $BAZecho jake実行します。

答え3

ここではいくつかの重要なことが起こっています。

  • 説明したようにバッシュリファレンスマニュアル、単純なコマンド拡張、「コマンド名の結果がない場合、変数の割り当ては現在のシェル環境に影響します。そうでなければ、コマンドが実行される環境に変数が追加されます。現在、シェル環境には影響しません。 「だからと言うと、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
    

また、違いはシェル環境に残っているBAZ=jake; echo $BAZ2つの別々のステートメントであることに注意してください。BAZ=jakeユースケースは意図によって異なります。これらの変数が必要な複数のプログラムを実行したい場合は、その変数が必要になることがありますexport。この特定の時間にのみ必要な場合は、変数を事前に割り当てる方が良いかもしれません。

答え4

簡単に言うと:

BAZ=jake echo $BAZ

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

Since は、コマンドが実行される前にはどの値も割り当てられず、以降は解析BAZBAZ=jakeにのみ考慮されるため、どの値でも確認されません。したがって、何も出力されません。$BAZ$BAZecho $BAZ

BAZ=jake指定されたコマンドの一部にすぎません(シェルはそれを環境変数として処理/設定しません)。この変数は、一部のプロセスが同じコマンドラインの一部として実行されるときに使用されます。これは便利ですBAZ。命令実行が完了すると、BAZの値が不安定になります。jake

たとえば、]# LD_LIBRARY_PATH="new_path" ldconfig、どこldconfig変数はコマンドによって内部的に参照され、上記とは異なり、LD_LIBRARY_PATHこのコマンドラインには変数拡張はありません。

その他の場合:

BAZ=jake; echo $BAZ  

1行に提供される2つの異なるコマンドです。 1つのタスクを順番に実行するのと同じです。

関連情報