我有一个巨大的文件(超过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会成功吗?
答案 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一次来搜索你的任何模式(我知道,这不是你想要的),并将其输出重定向到一个中间文件,然后对该中间文件进行多次传递,每个模式一次,每次都重定向到不同的最终输出文件。