私の同僚が私に慣れていない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 $BAZ
JAKEが印刷されない理由は、変数置換が他のものよりも先に行われるためです。変数置換をバイパスすると、期待どおりに機能します。
$ 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 $BAZ
てecho 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 $BAZ
2つの別々のステートメントであることに注意してください。BAZ=jake
ユースケースは意図によって異なります。これらの変数が必要な複数のプログラムを実行したい場合は、その変数が必要になることがありますexport
。この特定の時間にのみ必要な場合は、変数を事前に割り当てる方が良いかもしれません。
答え4
簡単に言うと:
BAZ=jake echo $BAZ
variable substitution
がコマンドで最初に発生するため、何も出力されません。これは、このコマンドラインで発生する最初の操作が、以前に定義された変数(存在する場合)の実際の値$BAZ
に置き換えられることを意味します。BAZ
これは、シェルがBAZ=jake
同じコマンドラインを考慮する前に発生します。
Since は、コマンドが実行される前にはどの値も割り当てられず、以降は解析BAZ
後BAZ=jake
にのみ考慮されるため、どの値でも確認されません。したがって、何も出力されません。$BAZ
$BAZ
echo $BAZ
BAZ=jake
指定されたコマンドの一部にすぎません(シェルはそれを環境変数として処理/設定しません)。この変数は、一部のプロセスが同じコマンドラインの一部として実行されるときに使用されます。これは便利ですBAZ
。命令実行が完了すると、BAZ
の値が不安定になります。jake
たとえば、]# LD_LIBRARY_PATH="new_path" ldconfig
、どこldconfig
変数はコマンドによって内部的に参照され、上記とは異なり、LD_LIBRARY_PATH
このコマンドラインには変数拡張はありません。
その他の場合:
BAZ=jake; echo $BAZ
1行に提供される2つの異なるコマンドです。 1つのタスクを順番に実行するのと同じです。