このコマンド:
A=10 echo $A
空の行を出力します。なぜ10
ではありませんか?インプレースの一時的な環境設定が機能しないのはなぜですか?
解決策よりも理由と説明を知りたい。
私は使った
LANG=C gcc ...
gccにシステム言語(中国語)の代わりにフォールバック言語(英語)を使用するように強制します。したがって、VAR=value
プレフィックスがそれに続くコマンドの一時的な環境をセットアップすると想定しています。しかし、私にはいくつかの誤解があるようです。
コマンドを評価するさまざまなステップが発生する順序の問題です。
A=10 echo $A
は、最初にコマンドを3つの単語A=10
、echo
、および$A
で構成される単純なコマンドに解析します。次に、各Wordで変数の置換、つまり$A
などの変数展開の値への変換が行われます(目に見えるものを何もしないステップは省略しています)。
A
の値が最初にfoo
である場合、展開ステップの結果は、A=10
、echo
、およびfoo
の3つの単語を含む単純なコマンドになります。 (シェルはこの時点で、どの文字が最初に引用符で囲まれていたかを記憶します。この場合はどれもありません。)次のステップはコマンドの実行です。 A=10
は有効な変数名で始まり、その後に等号が続くため、割り当てとして扱われます。変数のA
は、コマンドの実行中にシェルと環境の両方で10
に設定されます。 (通常、シェル変数としてだけでなく、環境内にA
を持つexport A
を記述する必要があります。これは例外です。次のWordは割り当てではないため、コマンド名として扱われます。 (これは組み込みコマンドです)。 echo
コマンドは変数に依存しないため、A=10 echo $A
はecho $A
とまったく同じ効果があります。
コマンドの実行中のみ変数を設定したいが、コマンドの実行中に割り当てを考慮する場合は、サブシェルを使用できます。括弧で示されたサブシェルは、すべての状態の変更(変数の割り当て、現在のディレクトリ、関数定義など)をサブシェルに対してローカルにします。
(A=10; echo $A)
変数を環境にエクスポートして、外部プログラムから見えるようにする場合は、export A=10
を作成します。
LANG=C gcc ...
を使用すると、シェルがgcc
の環境にLANGを設定しますonly、およびnotがcurrent環境自体に設定されます( 注を参照)。したがって、gcc
finishesの後、LANG
は以前の値に戻ります(または設定解除されます)。
さらに、A=10 echo $A
を使用すると、エコーではなく$ Aを置換するShellになり、この置換(「拡張」と呼ばれる)が発生しますbeforeステートメントは評価(割り当てを含む)であるため、期待どおりに機能するためには、A
の値が、そのステートメントの前にcurrent環境で既に設定されている必要があります。
A=10 echo $A
が期待どおりに機能しないのはそのためです。A=10
はエコーに対して設定されますが、エコーは内部的に環境変数A
の値を無視します。 $A
は、現在のシェル(なし)で設定された値に置き換えられ、thenはechoの引数として渡されます。
したがって、あなたの仮定は正しいです:VAR=value command
does work、しかしこれは内部的にcommand
ses VARの場合にのみ関連します。そうでない場合でも、value
をargumentとしてcommand
に渡すことができますが、引数はcurrentシェルに置き換えられるため、使用前に設定する必要があります:VAR=value; command "$VAR"
実行可能スクリプトの作成方法がわかっている場合は、テストとしてこれを試すことができます。
#!/bin/sh
echo "1st argument is $1"
echo "A is $A"
testscript
として保存して、試してください:
$ A=5; A=10 testscript "$A"; echo "$A"
1st argument is 5
A is 10
5
最後になりましたが、Shellとenvironment変数とプログラムargumentsの違いを知っておく価値があります。
以下に参考資料を示します。
。
(*)注:技術的にはシェルdoes現在の環境でも設定されます。その理由は次のとおりです。echo
、read
、test
などの一部のコマンドはShell builtinsです。子プロセスを生成しないでください。現在の環境で実行されます。ただし、シェルは、コマンドが実行されるまで割り当てが継続するだけなので、実際の目的ではすべて同じ効果があります。割り当てはその単一のコマンドによってのみ表示されます。
あなたが明らかに望んでいることをする1つのおそらくきれいな方法は、コマンドを発行することです:
A=10 eval 'echo $A'
実際には、値10の置換を$ Aの場所に後のコンテキスト(つまり、割り当てについて既に知っているevalの「内部」)に延期します。単一引用符は必須です。このような構造は、現在の環境を汚染するリスクを冒すことなく、割り当てを目的のコマンド(この場合はエコー)に明確に伝えます。