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