如何将输入拆分到两个管道

Hag*_*zen 9 command-line pipe

我想做一些与此等效的事情:

some-expensive-command > /tmp/mytempfile
grep -v "pattern" /tmp/mytempfile >> output.txt
grep "pattern" /tmp/mytempfile | yet-another-command
Run Code Online (Sandbox Code Playgroud)

最好是优雅且不需要tempfile. 我正在考虑通过管道tee,但我能想到的最好的可能是将三行中的两行组合起来,并且仍然需要中间存储:

some-expensive-command | tee /tmp/mytempfile | grep -v "pattern" >> output.txt
grep "pattern" /tmp/mytempfile | yet-another-command
Run Code Online (Sandbox Code Playgroud)

Ser*_*nyy 9

问题的读法听起来像是您希望将一个标准输入重定向到两个不同的命令。如果是这种情况,请利用tee加进程替换:

some-expensive-command | tee >(grep 'pattern' > output.txt) >(grep -v 'pattern' | another-command)
Run Code Online (Sandbox Code Playgroud)

进程替换实际上是 bash 本身(在子进程级别)内实现的匿名管道。我们还可以使用命名管道 + tee。例如,在终端 A 中执行

$ mkfifo named.fifo
$ cat /etc/passwd | tee named.fifo | grep 'root'
Run Code Online (Sandbox Code Playgroud)

在另一个航站楼 B 做

$ grep -v 'root' named.fifo
Run Code Online (Sandbox Code Playgroud)

另一种看待这个问题的方法是认识到这grep模式匹配工具,因此通过一次读取行并在多个命令中使用同一行,我们可以达到完全相同的效果:

some-expensive-command | tee >(grep 'pattern' > output.txt) >(grep -v 'pattern' | another-command)
Run Code Online (Sandbox Code Playgroud)

另一种方法是放弃grep并使用更强大的东西,例如awk

some-expensive-command | awk '/pattern/{print >> "output.txt"}; !/pattern/{print}' | another-command.
Run Code Online (Sandbox Code Playgroud)

实际上,不用担心使用临时文件,只要在使用后清理它们即可。如果有效,那就有效。


des*_*ert 2

使用bash流程替换

\n\n
some-command | tee >(grep "pat" | another-command >>out1) | grep -v "pat" >>out2\n
Run Code Online (Sandbox Code Playgroud)\n\n

进程替换将some-command\xe2\x80\x99s 输出分配给grep "pat"\xe2\x80\x99s 输入,从而保存临时文件。当然,数据仍然保存在文件中(总是\xe2\x80\x99s),只是你不必\xe2\x80\x99t 处理它。如果您不想将 \xe2\x80 another-command\x99s 输出保存在文件中而是打印它,我建议简单地切换两个命令列表。

\n\n

另一个不错的信息来源:man bash/EXPANSION

\n