evalとbashを介したパイプ

使用の違いは何ですか:

eval "echo "foo"" 

および

echo "echo "foo"" | bash 

何かありますか?

コメント

  • ここに'実行環境に関して動作がわずかに異なる別のバリエーション:( eval 'echo "foo"' )

回答

短い回答

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 Builtin )には、lastpipeオプションについて次のように記載されています。

lastpipe

設定されていて、ジョブ制御がアクティブでない場合、シェルはパイプラインで実行されていない最後のコマンドを実行します。現在のシェル環境の背景。

次のようにこれが当てはまることを確認できます。

最初にlastpipe

> shopt -s lastpipe 

次に、ジョブ制御を無効にします:

> set +m 

ここで、パイプ内から変数を設定するコマンドを実行します。

> unset x > echo x=42 | while IFS= read -r line; do eval "${line}"; done; > echo $x 42 

whileevalコマンドはstdinから入力を読み取ることができないため、回避策としてdiv>ループとreadコマンドを使用します(したがって、パイプ)。

この例は、パイプ内の右端のコマンドが実際に実行できることを示しています。 、現在のシェルで実行されます。ただし、これは実際には元の例には影響しません。 lastpipeを有効にしてジョブ制御を無効にしても、bashにパイプすると次の結果が得られます。

> echo "x=42" | bash; echo $x > 

これは、bashコマンド自体がサブシェルで入力を実行するためです。

コメント

  • これは良い観察です。'気づいていませんでしたが、そうですね' ■パイプのしくみ
  • 不思議なことに、答えを受け入れなかった理由は何ですか?
  • スクリプトの実行時(より正確には、ジョブ制御がオフのとき)のbash4.2以降の場合そして、shopt lastpipeが設定され、パイプラインはバックグラウンドではなく、'トップ'シェルはサブシェルではありません。 unix.stackexchange.com/questions/9954/ … および unix.stackexchange.com/questions/136206/readarray-or-pipe-issue
  • @ dave_thompson_085 bashコマンドは次の場所で実行できます。オプションによってはトップシェルですが、x=42は、サブシェルと合理的に呼ぶことができるもので確実に実行されます。
  • @AlexanderMills実際、パイプは

唯一の問題です。 bashコマンドは、パイプが含まれているかどうかに関係なく、サブシェルで入力を実行します。詳細については、ソリューションの更新を参照してください。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です