bashの置き換えとパイプの違いは何ですか?

bashの置き換えとパイプの違いは何ですか?

私は次の2つのコマンドを実行しています。

echo $(find ./ $OPT1 $OPT2 $OPT3)
echo find ./ $OPT1 $OPT2 $OPT3 | bash

奇妙なことに、topコマンドは結果を出ませんが、lowerコマンドは結果を返します。なぜそんなことですか?

答え1

最初はfind ./ $OPT1 $OPT2 $OPT3トークン化を実行し、グローバル(引用符なし)を出力し、それを印刷する$()ために渡します。echoこれはデフォルトでコマンドを実行するのと同じですfindが、改行文字は空白になり、ファイル名が含まれるかfind印刷されると拡張されます。しかし、コンテンツに異常なコンテンツが含まれている場合は、単語の分割も同様に奇妙です。 (他のものは参照されていないため、に渡される前に分割され、ワイルドカードされます。)*?IFS$OPT1find

2番目は、を印刷してfind ./ $OPT1 $OPT2 $OPT3変数を展開し(引用符がないので再分割してワイルドカードを使用)、結果をbashコマンドとして実行するために渡します。 running とほぼ同じですfindが、変数にシェルメタ文字が含まれている場合は、2番目のシェルによって(再び)拡張されます。

まず、ファイル名がfoo*拡張され、3つすべてがワイルドカードとして表示されます。

$ touch foo1 foo2 foo\*
$ echo $(find .)
. ./foo2 ./foo* ./foo1 ./foo2 ./foo1

第二に、bashのパイピングのために使用したものなどの内部変数が拡張されることに注意してくださいeval

$ OPT='echo $BASH_VERSION'
$ echo $OPT
echo $BASH_VERSION
$ echo $OPT | bash
4.3.30(1)-release
$ eval $OPT        # about the same  
4.3.30(1)-release

BASH_VERSION変数の拡張はおそらく最も簡単な例です。ただし、以下に示すように、いずれの場合もエクスポートした変数やシェル内の他の変数が必要です。 (find今では合理的な例は思い出せません。)

変数に含まれる内容によっては、追加の評価ラウンドで一致するかどうかがOPT異なります。find

関連情報