使用の違いは何ですか:
eval 'echo "foo"'
そして
echo 'echo "foo"' | bash
何かありますか?
eval
によって実行されるコマンドは現在のシェルで実行され、bash
にパイプされたコマンドはサブシェルで実行されます。例:
> echo 'x=42' | bash; echo $x
> eval 'x=42'; echo $x
42
コメントで、bash
(> = 4.2)のより新しいバージョンでは、最初のコマンドも同じ効果を持つ可能性があると主張されました。しかし、これはそうではないようです。
実際には、パイプされたコマンドが現在のセッションで実行されない原因となるいくつかの要因があります。パイプとbash
コマンドです。
ほとんどの場合、パイプされたコマンドはサブシェルで実行されます。 Bashマニュアル( セクション3.2.2:パイプライン )には、次のように書かれています。
パイプライン内の各コマンドは、独自のサブシェルで実行されます( コマンド実行環境 を参照)。
コメントで指摘されているように、この動作はlastpipe
オプションを使用して変更できます。 Bashマニュアル( セクション4.3.2:Shoptビルトイン )は、lastpipe
オプションについて次のように述べています。
ラストパイプ
設定され、ジョブ制御がアクティブでない場合、シェルは現在のシェル環境でバックグラウンドで実行されていないパイプラインの最後のコマンドを実行します。
これは、次のようにして確認できます。
最初にlastpipe
を有効にします。
> shopt -s lastpipe
次に、ジョブ制御を無効にします。
> set +m
次に、パイプ内から変数を設定するコマンドを実行します。
> unset x
> echo x=42 | while IFS= read -r line; do eval "${line}"; done;
> echo $x
42
while
コマンドはstdinから入力を読み取ることができないため、read
ループとeval
コマンドを回避策として使用していることに注意してください(したがって、パイプから入力を取得できません)。 。
この例は、パイプの右端のコマンドが実際には現在のシェルで実行できることを示しています。ただし、これは実際には元の例には影響しません。 lastpipe
を有効にし、ジョブ制御を無効にしても、bash
にパイプすると、次の結果が得られます。
> echo 'x=42' | bash; echo $x
>
これは、bash
コマンド自体がサブシェルで入力を実行するためです。