使用の違いは何ですか:
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 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
while
を使用していることに注意してください。 eval
コマンドは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
コマンドは、パイプが含まれているかどうかに関係なく、サブシェルで入力を実行します。詳細については、ソリューションの更新を参照してください。
( eval 'echo "foo"' )