Bash:プロセス置換と標準入力


13

次の行は明らかです。

echo "bla" | foo | bar

しかし、以下のものは同じことをしますか?

echo "bla" | bar <(foo)
echo "bla" | bar < <(foo)

どれが標準入力から「bla」foobar読み、なぜですか?

もちろん、コーディングして確認することはできますが、動作が定義されているのか、信頼すべきではない機能を利用しているのかはわかりません。

回答:


9

これはシェルに依存しており、文書化されていません。ksh及びbash、最初のケースでは、foo同様の標準入力を共有しますbar。彼らはの出力のために戦うでしょうecho

たとえば、

$ seq 10000 | paste - <(tr 1 X)'
1       X
2       X042
3       X043
4       X044
5       X045
[...]

の出力pasteからテキストの他のすべてのブロックを読み取り、他のブロックを読み取る証拠が表示されます。seqtr

zsh、それは外側の標準入力を取得します(それが端末であり、シェルがインタラクティブでない場合は、その場合にリダイレクトされます/dev/null)。ksh(元々)、zshおよびbashプロセス置換AFAIKをサポートする唯一のBourne風のシェルです。

ではecho "bla" | bar < <(foo)barのstdinはの出力によって供給されるパイプになることに注意してくださいfoo。それは明確に定義された振る舞いです。その場合、fooのstdinは、およびのechoすべてで供給されるパイプであるように見えます。kshzshbash

3つのシェルすべてで一貫した動作を行い、文書化されていないため動作が変更される可能性があるため、将来を見越したい場合は、次のように記述します。

echo bla | { bar <(foo); }

確かにfooの標準入力からもパイプであるecho(あなたががそれをやりたいと思いますなぜ私が見ることができません)。または:

echo bla | bar <(foo < /dev/null)

確認するにfooは、からのパイプから読み取らないでくださいecho。または:

{ echo bla | bar 3<&- <(foo <&3); } 3<&0

。のfoo現在のバージョンのように外側のstdin を持っていますzsh


「その場合、fooのstdinは、ksh、zsh、およびbashのすべてでechoによって供給されるパイプです。」あなたは今これを手でテストしましたか、それともどこかに文書化されていますか?
etam1024 14

最初の行の「最初の場合」は `|を参照します foo | bar`または `| bar <(foo) `?
フォルカーシーゲル14

4

echo "bla" | foo | bar:の出力echo "bla"はにリダイレクトされfoo、その出力はにリダイレクトされbarます。

echo "bla" | bar <(foo):の出力をecho "bla"toにパイプしますbar。しかしbar、引数付きで実行されます。引数は、出力fooが送信されるファイル記述子へのパスです。この引数は、の出力を含むファイルのように動作しますfoo。それで、それは同じではありません。

echo "bla" | bar < <(foo):の出力をecho "bla"送信する必要がbarあり、ステートメント全体が最初のものと同等であると仮定する場合があります。しかし、それは正しくありません。次のことが起こります。入力リダイレクト<はパイプ(|)の後に実行されるため、上書きされます。だからecho "bla"バーにパイプされていません。代わりに、の出力はfooへの標準入力としてリダイレクトされますbar。これをクリアするには、次のコマンドと出力を参照してください。

$ echo "bla" | cat < <(echo "foo")
foo

ご覧のとおり、にecho "bla"置き換えられecho "foo"ます。

次のコマンドを参照してください。

$ echo "bar" | cat < <(awk '{printf "%s and foo", $0}')
bar and foo

echo "bar"パイプされawk、stdinを読み取りand foo、出力に文字列を追加します。この出力はにパイプされcatます。


私の質問は、awk「「バー」と表示されているという事実は定義された動作ですか?」
etam1024 14

はい、そうです。cmd1 < <(cmd2)と同じように動作しcmd2 | cmd1ます。
カオス14

またはcmd1 | cmd2 | cmd3と同じですcmd1 | cmd3 < <(cmd2)
カオス14

3
それがウィキペディアだった場合、私はあなたの声明に「要出典」タグを付けました:)私の質問の全体的なポイントは、あなたが言うように機能するということですが、それに関するドキュメントを見つけることができませんでした。
etam1024 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.