web-dev-qa-db-ja.com

envを使用してbashで1つのプログラム呼び出しの環境変数を設定する

envコマンドを使用して、環境を変更したシェルコマンドを起動しようとしています。

マニュアルによると

env HELLO='Hello World' echo $HELLO

Hello World、しかしそうではありません。私が行った場合

HELLO='Hello World' bash -c 'echo $HELLO'

Hello World期待どおり(この情報について この回答 に感謝)。

ここで何が欠けていますか?

乾杯、ニクラス

31
Niklas

最初のケースでは、現在のシェルがコマンドを実行する前に$ HELLO変数を展開するためです。また、現在のシェルにはHELLO変数が設定されていません。

env HELLO='Hello World' echo $HELLO

これを行います:

  • 指定された変数を展開します。この場合は$ HELLO
  • 3つの引数「HELLO = Hello World」、「echo」、および ''(現在のシェルにはHELLO変数が設定されていないため、空の文字列)を指定してenvを実行します。
  • Envコマンドが実行され、その環境でHELLO = 'Hello World'が設定されます
  • envは引数 ''(空の文字列)でエコーを実行します

ご覧のように、現在のシェルは$ HELLO変数を拡張しましたが、これは設定されていません。

HELLO='Hello World' bash -c 'echo $HELLO'

これを行います:

  • 変数HELLO='Hello Worldを次のコマンドに設定します
  • 2つの引数「-c」と「echo $ HELLO」を指定してbashを実行します
  • 最後の引数は一重引用符で囲まれているため、その内部は拡張されません
  • 新しいbashはecho $HELLOコマンドを実行します
  • 新しいbashサブシェルでecho $ HELLOを実行するために、bashは最初に可能な限りすべてを展開します。この場合は$ HELLOであり、親シェルはそれを "Hello World"に設定します。
  • サブシェルはエコー「Hello World」を実行します

あなたがやろうとした場合この:

env HELLO='Hello World' echo '$HELLO'

  • 現在のシェルはできる限り何でも展開しますが、$ HELLOは一重引用符で囲まれているため、何も拡張されません
  • 3つの引数「HELLO = Hello World」、「echo」、「$ HELLO」を指定してenvを実行します
  • Envコマンドが実行され、その環境でHELLO = 'Hello World'が設定されます
  • envは引数 '$ HELLO'でエコーを実行します

この場合、$ HELLOを展開するシェルはないため、echoは文字列$HELLOを受け取り、それを出力します。変数の展開は、シェルによってのみ行われます。

46
nos

何が起こるかは、私も困惑した この状況 に似ていると思います。

簡単に言えば、最初のケースでの変数の展開は、その環境に$HELLOがない現在のシェルによって行われます。ただし、2番目のケースでは、単一引用符によって現在のシェルが変数を展開できないため、すべてが期待どおりに機能します。

一重引用符を二重引用符に変更すると、このコマンドが希望どおりに機能しなくなることに注意してください。

HELLO='Hello World' bash -c "echo $HELLO"

これは、質問の最初のコマンドと同じ理由で失敗します。

4
Lev Levitsky

これは機能し、私にとっては良いことです

$ MY_VAR='Hello' ANOTHER_VAR='World!!!' && echo "$MY_VAR $ANOTHER_VAR"
Hello World!!!
2
deFreitas

シェルが期待どおりに機能していることを確認する簡単な方法を次に示します。

env A=42 env
env

最初のコマンドを実行すると、Aが42に設定され、envが実行されます。 2番目のコマンドは、runs envも実行します。両方の出力を比較します。

1