Grep到多个输出文件

时间:2011-12-02 22:54:00

标签: bash awk grep

我有一个巨大的文件(超过6GB)和大约1000个模式。我希望提取线匹配每个模式以分隔文件。例如,我的模式是:

1
2

我的档案:

a|1
b|2
c|3
d|123

作为输出,我想有2个文件:

1:

a|1
d|123

2:

b|2
d|123

我可以通过多次greping文件来做到这一点,但对1000个模式和大文件来说效率很低。我也试过这样的事情:

grep -f pattern_file huge_file

但它只会生成1个输出文件。我无法对我的庞大文件进行排序 - 这需要花费很多时间。也许AWK会成功吗?

5 个答案:

答案 0 :(得分:5)

awk -F\| 'NR == FNR {
  patt[$0]; next
  }
{
  for (p in patt)
    if ($2 ~ p) print > p
  }' patterns huge_file

使用一些awk实现,您可能会达到最大打开文件数限制。 如果是这种情况,请告诉我,以便我可以发布替代解决方案。

P.S。:此版本一次只能打开一个文件:

awk -F\| 'NR == FNR {
  patt[$0]; next
  }
{
  for (p in patt) {
    if ($2 ~ p) print >> p
    close(p)
    }
  }' patterns huge_file

答案 1 :(得分:4)

您可以使用bash“进程替换”来完成此操作(如果我理解了这个问题),例如,请考虑以下示例数据:

$ cal -h
   September 2013     
Su Mo Tu We Th Fr Sa  
 1  2  3  4  5  6  7  
 8  9 10 11 12 13 14  
15 16 17 18 19 20 21  
22 23 24 25 26 27 28  
29 30 

然后,在一个命令中,选择行可以grep到不同的输出文件:

$ cal -h \
    | tee >( egrep '1'    > f1.txt ) \
    | tee >( egrep '2'    > f2.txt ) \
    | tee >( egrep 'Sept' > f3.txt ) 

在这种情况下,每个grep正在处理整个数据流(可能是您想要的也可能不是:这可能不会节省大量时间而只是运行并发grep进程) :

$ more  f?.txt
::::::::::::::
f1.txt
::::::::::::::
   September 2013     
 1  2  3  4  5  6  7  
 8  9 10 11 12 13 14  
15 16 17 18 19 20 21  
::::::::::::::
f2.txt
::::::::::::::
   September 2013     
 1  2  3  4  5  6  7  
 8  9 10 11 12 13 14  
15 16 17 18 19 20 21  
22 23 24 25 26 27 28  
29 30                 
::::::::::::::
f3.txt
::::::::::::::
   September 2013     

答案 2 :(得分:1)

这可能对你有用(虽然sed可能不是最快的工具!):

 sed 's,.*,/&/w &_file,' pattern_file > sed_file

然后针对来源运行此文件:

 sed -nf sed_file huge_file

我做了一个粗略的测试和我正在使用的GNU sed version 4.1.5,很容易打开1000个文件OK,但是你的unix系统可能有更小的限制。

答案 3 :(得分:0)

Grep无法将不同模式的匹配输出到不同的文件。 Tee能够将其输入重定向到多个目的地,但我认为这不是你想要的。

使用多个grep命令或编写程序以Python或其他任何您喜欢的语言来执行此操作。

答案 4 :(得分:0)

我有这个需要,所以我把这个功能添加到我自己的grep.c副本中,我碰巧躺在那里。但它只是发生在我身上:如果主要目标是避免多次传递一个巨大的输入,你可以在巨大的输入上运行egrep一次来搜索你的任何模式(我知道,这不是你想要的),并将其输出重定向到一个中间文件,然后对该中间文件进行多次传递,每个模式一次,每次都重定向到不同的最终输出文件。