2012-12-21 12 views
21

コマンドenvで変更された環境でシェルコマンドを呼び出そうとしています。envを使用してbashで1つのプログラム呼び出しの環境変数を設定する

は手動

env HELLO='Hello World' echo $HELLO 

によるHello Worldをエコーする必要がありますが、それはしていません。私は

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

を行う場合、期待どおり それは(この情報のためthis answerのおかげで)Hello Worldを出力します。

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

乾杯、 ニクラス

+0

拡張が全くないサニティチェックは、 'HELLO = 'Hello World' env | grep HELLO'は要求されたことをしますが、実際には受け入れられた答えよりもあまり有用ではありません。 –

答えて

37

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

  • '、
  • $ハローこの場合には、3つの引数のハロー=のHello World'が実行ENVを与えられたすべての変数を展開する 'エコー' と:

    env HELLO='Hello World' echo $HELLO

    はこれを行います'(現在のシェルにHELLO変数が設定されていないので空文字列です)

  • envコマンドは、その環境でHELLO =' Hello World 'を実行して設定します。
  • envが実行されます引数 ''(空の文字列)でエコーする

現在のシェルは、設定されていない$ HELLO変数を展開しています。以来

  • は、次のコマンドのための変数HELLO='Hello World 2つの引数の-c "と
  • 実行bashの設定と 'ハロー$エコー'
  • HELLO='Hello World' bash -c 'echo $HELLO'

    はこれを行います最後の引数は一重引用符で囲まれています。その中にあるものは展開されません。

  • 新しいbashは順番にコマンドを実行します
  • 新しいbashサブシェルでecho $ HELLOを実行するには、bashはまず何かを展開します。この場合は$ HELLO、親シェルは "Hello World"に設定します。
  • サブシェルが実行され、エコー 'のHello World' あなたは、例えばを実行しようとしました場合は

この:

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

  • 現在のシェルが$ハローは、単一引用符で囲まれているので何もありませんそれができる何かを、拡大する
  • 3つの引数のハロー=のHello World "と
  • 実行ENV 'エコー」と '$ハロー '$ハロー
を 'ENVは、引数でエコーを実行します
  • その環境の中で' Hello Worldの'
  • envコマンドは=のHELLOを実行し、設定されます'

    この場合、$ HELLOを展開するシェルはないので、echoは文字列$HELLOを受け取り、それを表示します。変数の展開はシェルのみで行われます。

  • 4

    私は何が起こることは私も困惑しているthis situationに似ていると思います。

    一言で言えば、最初のケースの変数展開は、その環境に$HELLOを持たない現在のシェルによって行われます。しかし、二重引用符では、一重引用符では現在のシェルが変数展開を行わないので、すべてが期待どおりに機能します。二重引用符に単一引用符を変更すると、あなたが望むように働いてから、このコマンドを防ぐ方法

    注:

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

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

    +0

    正しい。最初のケースでは、変数を展開するのは現在のシェルです。後者の場合、新しい 'bash'が実行されています。 –

    +0

    また、ここにはすばやく返信いただきありがとうございます!残念なことに、私は1つの答えに素敵な緑色のダニを与えることができます – Niklas

    2

    これは動作しますし、私

    $ MY_VAR='Hello' ANOTHER_VAR='World!!!' && echo "$MY_VAR $ANOTHER_VAR" 
    Hello World!!! 
    
    +1

    質問の "for one program call"の部分にはこれがないと思います。ここのバールは、現在のセッションに合わせて設定されたままになるので、引き続きエコーを続けることができます。 –

    0

    がここで期待どおりに動作しているシェルを確認する簡単な方法があるのために良いです。

    env A=42 env 
    env 
    

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

    関連する問題