コマンドラインで環境変数を設定し、コマンドに表示するにはどうすればよいですか?


152

走ったら

export TEST=foo
echo $TEST

fooを出力します。

走ったら

TEST=foo echo $TEST

ありません。エクスポートまたはスクリプトを使用せずにこの機能を取得するにはどうすればよいですか?


注意してください、この物語には最初に現れる以上のものがあります。私の答えを確認してください。
ジェイソンレオンハルト

回答:


180

これは、実際にコマンドを実行するにシェルがコマンドラインの変数を展開し、その時点で変数が存在しないためです。使用する場合

TEST=foo; echo $TEST

それが動作します。

export変数は、その後実行されるコマンドの環境に表示されます(bashでの動作については、を参照してくださいhelp export)。1つのコマンドの環境に変数を表示するだけでよい場合は、試したものを使用します。

TEST=foo your-application

1
/ usr / bin / envはどうですか?それも機能しません、理由を知っていますか?
ベヌバード14

5
同じ理由- $TESTコマンドラインが実行される前にシェルが展開します。一度echo実行されている(また、それは注意してecho、通常は組み込みコマンドシェルに変換しないようになり/bin/echo、それがその環境での変数のセットを見ています)。ただし、その環境から変数の内容を出力するecho $TESTように指示echoしませんTESTecho現在呼び出されている変数にあるものを引数として実行するようにシェルに指示しますTEST。これらは2つの非常に異なるものです。
ペテルフ14

@peterph実際にコマンドを実行する前にシェルがコマンドラインの変数を展開する場合、なぜ展開しないのvar=value sh -c 'echo "$var"'ですか?
ハック

私はあなたに説明したように、ここで:変数は二重引用符の内側に展開されるので、それはです(例えば、"… $var …")ではなく、単一引用符の内側(例えば、'… $var …')。echo "$var"は単一引用符の内側にあるため、その文字列全体sh -cは、外部のインタラクティブシェルによって解釈されることなく、新しい()シェルに渡されます。…(続き)
Gマン

(続き)… igalが昨日言ったように、解析には2つのラウンドがあります。親シェルによって実行される解析とは別に、 2ラウンドの解析ありません。解析には2つのラウンドがあります。1つは外部のインタラクティブ(親)シェルによって実行され、もう1つは新しい(sh -c)子シェルによって実行されます。
Gマン

39

環境変数ではなく、シェル変数のスコープを制限したいのではないでしょうか。環境変数は、それらがされたときにコマンドに渡された文字列のリストです実行します

var=value echo whatever

var=valueエコーが受信する環境に文字列を渡します。ただし、echoその環境リストでは何もせず、とにかくほとんどのシェルでecho組み込まれているため、実行されません。

あなたが書いていた場合

var=value sh -c 'echo "$var"'

それは別の問題だったでしょう。ここではvar=valueshコマンドに渡していますが、shたまたまその環境を使用しています。シェルは、環境から受け取る各変数をシェル変数に変換するため、var環境変数がsh受け取る変数は変数に変換され、$varそのechoコマンドラインで展開すると、になりecho valueます。環境はデフォルトで継承されるため、環境内でechoも受信var=valueします(または実行された場合は受信します)がecho、環境については気にしません。

さて、私が疑うように、シェル変数のスコープを制限したい場合、いくつかの可能なアプローチがあります。

移植可能(BourneおよびPOSIX):

(var=value; echo "1: $var"); echo "2: $var"

上記の(...)はサブシェル(ほとんどのシェルの新しいシェルプロセス)を開始するため、そこで宣言された変数はそのサブシェルにのみ影響するため、上記のコードは「1:value」を出力するはずですおよび「2:」または「2:whatever-var-was-set-to-before」。

ほとんどのBourneライクシェルでは、関数と「ローカル」ビルトインを使用できます。

f() {
  local var
  var=value
  echo "1: $var"
}
f
echo "2: $var"

zshでは、インライン関数を使用できます。

(){ local var=value; echo "1: $var"; }; echo "2: $var"

または:

function { local var=value; echo "1: $var"; }; echo "2: $var"

bashとzsh(ash、pdksh、AT&T kshではない)を使用すると、このトリックも機能します。

var=value eval 'echo "1: $var"'; echo "2: $var"

さらにいくつかのシェルで動作バリアント(dashmkshyash)ではなくzsh(でない限りsh/ kshエミュレーション):

var=value command eval 'echo "1: $var"'; echo "2: $var"

(POSIXシェルのcommand特別な組み込み(ここeval)の前で使用すると、その特殊性が削除されます(ここで、変数の割り当ては、それらから返された後も有効です)


私の目的にとって、これは正しい解決策です。受け入れられた答えのように、変数 'var'が環境を汚染しないようにします。
kronenpj

6

あなたはそれを正しくやっていますが、bash構文は誤解されやすいです:env var を取得してから印刷するecho $TEST原因と考えることができますが、そうではありません。だから与えられたechoTEST

export TEST=123

それから

TEST=456 echo $TEST

次のシーケンスが含まれます。

  1. シェルはコマンドライン全体を解析し、すべての変数置換を実行するため、コマンドラインは

    TEST=456 echo 123
  2. コマンドの前に設定された一時変数を作成し、現在の値を保存TESTして456で上書きします。コマンドラインは今

    echo 123
  3. 残りのコマンドを実行します。この場合、123をstdoutに出力します(そのため、残っているシェルコマンドはの一時値を使用しませんでしたTEST)。

  4. の値を復元します TEST

代わりにprintenvを使用してください。変数の置換が含まれていないためです。

>> export TEST=123
>> printenv TEST
123
>> TEST=456 printenv TEST
456
>> printenv TEST && TEST=456 printenv TEST && TEST=789 printenv TEST && printenv TEST
123
456
789
123
>>

+1 printenvテスト/概念実証に役立つことがわかった(スクリプトではなく、スクリプトのように動作するecho
ダリン

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