eta*_*024 13 bash process-substitution stdin
下面一行很明显:
echo "bla" | foo | bar
Run Code Online (Sandbox Code Playgroud)
但是下面的人也这样做吗?
echo "bla" | bar <(foo)
echo "bla" | bar < <(foo)
Run Code Online (Sandbox Code Playgroud)
哪个foo和bar从标准输入读取“bla”,为什么?
我的意思是,当然,我可以编写代码并检查它,但我不确定它是定义的行为还是我正在利用我不应该依赖的功能。
那是依赖于外壳的,没有记录在案的 AFAICS。在ksh和 中bash,在第一种情况下,foo将与 共享相同的标准输入bar。他们将为 的输出而战echo。
所以例如在,
$ seq 10000 | paste - <(tr 1 X)'
1 X
2 X042
3 X043
4 X044
5 X045
[...]
Run Code Online (Sandbox Code Playgroud)
您会看到paste从seq的输出中读取所有其他文本块同时tr读取其他文本块的证据。
使用zsh,它获取外部标准输入(除非它是终端并且外壳不是交互式的,在这种情况下它是从 重定向的/dev/null)。ksh(它的起源地),zsh并且bash是唯一支持进程替换 AFAIK 的类似 Bourne 的 shell。
在 中echo "bla" | bar < <(foo),请注意,bar的 stdin 将是由foo. 这是定义明确的行为。在这种情况下,foo的 stdin似乎是echo所有ksh,zsh和 中的管道bash。
如果您希望在所有三个 shell 中都有一致的行为并且是面向未来的,因为行为可能会因为没有记录而改变,我会写它:
echo bla | { bar <(foo); }
Run Code Online (Sandbox Code Playgroud)
可以肯定foo的是, stdin 也是来自的管道echo(我不明白你为什么要这样做)。或者:
echo bla | bar <(foo < /dev/null)
Run Code Online (Sandbox Code Playgroud)
为了确保foo不会不从管道中读取echo。或者:
{ echo bla | bar 3<&- <(foo <&3); } 3<&0
Run Code Online (Sandbox Code Playgroud)
拥有foo的标准输入外标准输入像的最新版本zsh。