我想在管道输入上运行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
Run Code Online (Sandbox Code Playgroud)
预期产出
Hello Boy
Hello World
Run Code Online (Sandbox Code Playgroud)
实际输出
Hello Boy
Run Code Online (Sandbox Code Playgroud)
我尝试过使用三通
cat mult_comm.sh
tee >(sed 's/World/Boy/g'|grep Boy) | grep World
Run Code Online (Sandbox Code Playgroud)
但这只是给出了
Hello World
Run Code Online (Sandbox Code Playgroud)
我可以根据需要修改.sh文件,但无法更改管道命令.有任何想法吗?
这与OS X/Linux类似:管道分为两个进程?和管道输出到两个不同的命令,但我无法弄清楚如何在脚本中使用命名管道.
ric*_*ici 14
当你执行
tee >(some_command)
Run Code Online (Sandbox Code Playgroud)
bash创建一个子shell来运行some_command.子壳stdin被分配给管道的读数的一半.bash在命令行中保留此管道的名称,以便tee将其输入泵入管道.子壳的stdout并stderr保持不变,所以它们仍然是相同tee的.
所以,当你执行
tee >(some_command) | some_other_command
Run Code Online (Sandbox Code Playgroud)
现在,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
Run Code Online (Sandbox Code Playgroud)
我们最终得到:
--> sed 's/World/Boy/g' --> grep Boy --
/ \
input --> tee --< \
\ \
----------------------------------------------> grep World
Run Code Online (Sandbox Code Playgroud)
在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
Run Code Online (Sandbox Code Playgroud)
如上所述阅读bashisms需要一些练习.重要的是那个
( commands ) 5>&1
Run Code Online (Sandbox Code Playgroud)
创建一个subshell(( ))并为该子shell赋予一个编号为5的fd,最初从stdout(5>&1)复制.在子shell中,/dev/fd/5指的是那个fd.在子shell中,可以重定向stdout,但是在将stdout复制到fd5之后会发生这种情况.