通过管道连接到 shell 中的多个文件

通过管道连接到 shell 中的多个文件

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

JUNK
JUNK
JUNK
JUNK
A 1
JUNK
B 5
C 1
JUNK

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

./app | grep A > A.out
./app | grep B > B.out
./app | grep C > C.out

这会让我得到我想要的东西,但是需要很长时间。我也不想将所有输出转储到单个文件并对其进行解析。

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

答案1

如果你有球座

./app | tee >(grep A > A.out) >(grep B > B.out) >(grep C > C.out) > /dev/null

(从这里

关于进程替换

答案2

您可以使用awk

./app | awk '/A/{ print > "A.out"}; /B/{ print > "B.out"}; /C/{ print > "C.out"}'

答案3

你也可以使用你的 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

甚至:

./app | while read line; do for foo in A B C; do 
     [[ "$line" =~ "$foo" ]] && echo $line >> "$foo".out; 
  done; done

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

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

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

答案4

这是 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/'

相关内容