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

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

次の行は明らかです。

echo "bla" | foo | bar

しかし、私の下の人々もそうしますか?

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

標準入力から「bla」を読むのはなぜですかfoobar

もちろん、コーディングして確認することはできますが、定義された動作であるか、依存してはいけない機能を活用しているかどうかはわかりません。

答え1

これはシェルによって異なり、AFAICS に文書化されていません。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端末からcmd &)。ksh(原産地)プロセスの交換をサポートする唯一のBourne様シェルですzshbash

では、stdinがの出力から提供されるパイプであることにecho "bla" | bar < <(foo)注意してください。これは明確に定義された動作です。この場合、stdinがすべてであるように見え、パイプも提供されます。barfoofooechokshzshbash

3つのシェルすべてで一貫した動作が必要になり、動作が文書化されずに変更される可能性があるため、将来も備えたい場合は、次のように作成します。

echo bla | { bar <(foo); }

確かにfoostdinもパイプから出てきますecho(しかし、なぜそうしたいのかわかりません)。または:

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

foo確認してくださいいいえパイプから読みますecho。または:

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

fooの現在のバージョンと同じMakeのstdin外部標準入力ですzsh

答え2

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

echo "bla" | bar <(foo):出力echo "bla"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"パイプで接続すると、awkstdinを読み込み、文字列をand foo出力に追加します。この出力はcat

関連情報