我想在管道输入上运行2个命令,并要打印(输出到stdout)两者的输出。
每个命令都是grep,sed和awk的组合。
这两个命令必须驻留在单个.sh文件中。
示例命令:
cat mult_comm.sh
sed 's/World/Boy/g'|grep Boy ; grep World
# Input
cat input.log
Hello World
# This command HAS to work EXACTLY like this
cat input.log | bash mult_comm.sh
预期产量
Hello Boy
Hello World
实际产量
Hello Boy
我尝试使用tee
cat mult_comm.sh
tee >(sed 's/World/Boy/g'|grep Boy) | grep World
但这只会给
Hello World
我可以根据需要修改.sh文件,但是无法更改管道命令。有任何想法吗?
这类似于OS X / Linux: pipe into two processes?和Pipe output to two different commands,但是我不知道如何在脚本中使用命名管道。
最佳答案
执行时
tee >(some_command)
bash创建一个子 shell 来运行
some_command
。子 shell 的stdin
分配给管道的读取部分。 bash在命令行上保留该管道的名称,以便tee
将其输入泵入管道。子 shell 的stdout
和stderr
保持不变,因此它们仍然与tee
相同。所以,当你执行
tee >(some_command) | some_other_command
现在,bash首先创建一个运行
tee
的进程,并将其stdout
分配给管道的写入部分,再创建一个运行some_other_command
的进程,将其stdin
分配给同一管道的读取部分。然后,它如上所述创建另一个进程以运行some_command
,将其stdin
分配给另一个管道的读取一半,并使其stdout
和stderr
保持不变。但是,stdout
已经被重定向到some_other_command
,这就是some_command
继承的。在您的实际示例中,
tee >(sed 's/World/Boy/g'|grep Boy) | grep World
我们最终得到:
--> sed 's/World/Boy/g' --> grep Boy --
/ \
input --> tee --< \
\ \
----------------------------------------------> grep World
在OP中链接的问题之一中,F. Hauri提供了一个(不被接受但正确的)答案,我在这里进行了调整:
echo Hello World |
((tee /dev/fd/5 | grep World >/dev/fd/4) \
5>&1 | sed 's/World/Boy/' | grep Boy) 4>&1
阅读上面的bashisms需要一些练习。重要的是
( commands ) 5>&1
创建一个子shell(
( )
)并为该子shell提供一个编号为5的fd,该文件最初是从stdout
(5>&1
)复制而来的。在子 shell 中,/dev/fd/5
引用该fd。在子 shell 中,可以重定向stdout
,但这将在将stdout复制到fd5之后发生。关于bash - Shell-管道传输到文件中的多个命令,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17983777/