管道到 shell 中的多个文件

sj7*_*755 31 shell grep bash pipe

我有一个应用程序会产生大量我不想存储到磁盘上的数据。该应用程序主要输出我不想使用的数据,而是一组必须拆分为单独文件的有用信息。例如,给定以下输出:

JUNK
JUNK
JUNK
JUNK
A 1
JUNK
B 5
C 1
JUNK
Run Code Online (Sandbox Code Playgroud)

我可以像这样运行应用程序三次:

./app | grep A > A.out
./app | grep B > B.out
./app | grep C > C.out
Run Code Online (Sandbox Code Playgroud)

这会让我得到我想要的,但需要太长时间。我也不想将所有输出转储到一个文件中并通过它进行解析。

有没有什么方法可以将上面显示的三个操作组合在一起,这样我只需要运行一次应用程序,仍然可以获得三个单独的输出文件?

Aur*_*oms 80

如果你有T 恤

./app | tee >(grep A > A.out) >(grep B > B.out) >(grep C > C.out) > /dev/null
Run Code Online (Sandbox Code Playgroud)

(从这里

关于进程替换

  • 鉴于问题的原始标题“管道到多个进程”,此答案是目前唯一准确的答案。 (7认同)
  • 太棒了,这也可以呈现为:`./app | tee >(grep A > A.out) >(grep B > B.out) | grep C > C.out` (4认同)
  • +1。这是最普遍适用的答案,因为它不依赖于特定过滤命令是“grep”这一事实。 (3认同)

Rah*_*til 32

您可以使用 awk

./app | awk '/A/{ print > "A.out"}; /B/{ print > "B.out"}; /C/{ print > "C.out"}'
Run Code Online (Sandbox Code Playgroud)

  • 问题的标题是管道到多个**进程**,这个答案是关于“管道”(由正则表达式调度)到多个**文件**。由于此答案已被接受,因此应相应更改问题的标题。 (6认同)

ter*_*don 17

您还可以使用 shell 的模式匹配功能

./app | while read line; do 
     [[ "$line" =~ A ]] && echo $line >> A.out; 
     [[ "$line" =~ B ]] && echo $line >> B.out; 
     [[ "$line" =~ C ]] && echo $line >> C.out; 
 done
Run Code Online (Sandbox Code Playgroud)

甚至:

./app | while read line; do for foo in A B C; do 
     [[ "$line" =~ "$foo" ]] && echo $line >> "$foo".out; 
  done; done
Run Code Online (Sandbox Code Playgroud)

一种更安全的方法,可以处理以 开头的反斜杠和行-

./app | while IFS= read -r line; do for foo in A B C; do 
     [[ "$line" =~ "$foo" ]] && printf -- "$line\n" >> "$foo".out; 
  done; done
Run Code Online (Sandbox Code Playgroud)

正如@StephaneChazelas 在评论中指出的那样,这不是很有效。最好的解决方案可能是@AurélienOoms'


Asy*_*abs 9

如果您有多个内核并且希望进程并行,则可以执行以下操作:

parallel -j 3 -- './app | grep A > A.out' './app | grep B > B.out' './app | grep C > C.out'
Run Code Online (Sandbox Code Playgroud)

这将在并行内核中产生三个进程。如果您希望有一些输出到控制台或主文件,它的优点是将输出保持在某种顺序,而不是混合它。

Ole Tange的 gnu 实用程序parallel可以从名称为parallelmoreutils 的大多数存储库中获得。来源可以从Savannah.gnu.org获得。另外一个介绍教学视频是在这里

附录

使用更新版本的并行(不一定是您的发行版存储库中的版本),您可以使用更优雅的构造:

./app | parallel -j3 -k --pipe 'grep {1} >> {1}.log' ::: 'A' 'B' 'C'
Run Code Online (Sandbox Code Playgroud)

这实现了在单独的内核或线程中运行一个 ./app 和 3 个并行 grep 进程的结果(由并行本身决定,也认为 -j3 是可选的,但在本示例中提供它是出于指导目的)。

可以通过执行以下操作获得更新版本的并行:

wget http://ftpmirror.gnu.org/parallel/parallel-20131022.tar.bz2
Run Code Online (Sandbox Code Playgroud)

然后通常的解压,cd到parallel-{date},./configure && make,sudo make install。这将安装 parallel、man page parallel 和 man page parallel_tutorial。


小智 7

这是 Perl 中的一个:

./app | perl -ne 'BEGIN {open(FDA, ">A.out") and 
                         open(FDB, ">B.out") and 
                         open(FDC, ">C.out") or die("Cannot open files: $!\n")} 
                  print FDA $_ if /A/; print FDB $_ if /B/; print FDC $_ if /C/'
Run Code Online (Sandbox Code Playgroud)