Answers:
那是壳依赖的,没有文档AFAICS。在ksh
和中bash
,在第一种情况下,foo
将与共享相同的stdin bar
。他们将为的输出而战echo
。
例如,在
$ seq 10000 | paste - <(tr 1 X)'
1 X
2 X042
3 X043
4 X044
5 X045
[...]
您会看到证据,该证据paste
从seq
的输出中读取每个其他文本块,同时tr
读取其他文本块。
使用zsh
,它将获得外部标准输入(除非它是一个终端,并且外壳不是交互式的,在这种情况下,它是从重定向的/dev/null
)。ksh
(起源于此),zsh
并且bash
是唯一支持流程替换AFAIK的类Bourne外壳。
在中echo "bla" | bar < <(foo)
,请注意,bar
stdin将是的输出馈送的管道foo
。这是定义明确的行为。在这种情况下,似乎foo
的标准输入是通过供给管echo
中的所有的ksh
,zsh
和bash
。
如果您希望在所有三个外壳上都具有一致的行为,并且要面向未来,因为该行为可能会因未记录而有所变化,请编写以下代码:
echo bla | { bar <(foo); }
为了确保foo
stdin也是管道echo
(我看不出为什么要这么做)。要么:
echo bla | bar <(foo < /dev/null)
为了确保foo
不会不从管道中读取echo
。要么:
{ echo bla | bar 3<&- <(foo <&3); } 3<&0
要拥有foo
标准输入,如外部版本的标准输入一样zsh
。
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"
通过管道传递给awk
,后者读取stdin并将字符串添加and foo
到输出中。此输出通过管道传输到cat
。
awk
读“条” 的事实是否是已定义的行为?”
cmd1 < <(cmd2)
的行为与相同cmd2 | cmd1
。
cmd1 | cmd2 | cmd3
等于cmd1 | cmd3 < <(cmd2)