如何在进程替换中读取标准输入?

如何在进程替换中读取标准输入?

我想将标准输出发送到多个命令,但是我不确定如何从进程替换中的标准输入读取?

我的尝试:

$ echo foo >(cat /dev/stdin) >(cat /dev/stdin)
foo /dev/fd/63 /dev/fd/62

$ echo foo >(cat -) >(cat -)
foo /dev/fd/63 /dev/fd/62

$ echo foo >(cat <&3) >(cat <&3) 3<&0
foo /dev/fd/63 /dev/fd/62
-bash: 3: Bad file descriptor
-bash: 3: Bad file descriptor

同一问题的替代版本:

$ cat file | tee &>/dev/null >(cmd1 /dev/stdin) >(cmd2 /dev/stdin)

这样做的正确方法是什么?

答案1

这是从标准输入读取的:

echo foo | tee >(read line </dev/stdin; echo "internal $line")

您必须记住,进程替换的行为“就像”文件。
它可以用在需要文件的地方。命令 tee 期望写入文件。
在该命令中,我们具体指定要读取的设备:/dev/stdin。在这个简单的例子中,/dev/stdin 可以被删除,这也将起作用:

echo foo | tee >(read line; echo "internal $line")

如果我正确理解您的需求,这将会起作用:

$ echo foo | tee >(read a </dev/stdin; echo "a is $a") \
>(read b </dev/stdin; echo "b is $b") \
>(read c </dev/stdin; echo "c is $c")
foo
a is foo
c is foo
b is foo

我省略了 PS2 提示以减少混乱。请注意,每个进程替换都会替换文件的使用(如tee FILE FILE ....:)。

读取不一定是第一个命令。

$ echo foo > >(echo "hello" | read b; read a </dev/stdin; echo "a is $a") 
a is foo

请注意,这里的“进程替换”需要重定向,
这就是这两个习惯用法的原因> >(

一个简单的 echo,只会打印所使用的 fd 的编号(文件名):

$ echo >(echo "hello")
/dev/fd/63
hello

它类似于:

$ echo "$file"
filename

然而这是一个非常不同的习语:

$ echo > "$file"

相关内容