假设我有一个文件,必须在其中搜索多个正则表达式,并且必须计算每个正则表达式的匹配数。
因此,我无法组合这些模式:
grep -Po '{regex_1}|{regex_2}|...|{regex_n}' file | wc -l
...因为每个正则表达式的出现次数是必需的。
我显然可以:
occurences[i]=$(grep -Po "${regex[i]}" file | wc -l)
...但不幸的是,遇到的文件可能非常大(> 1 GB),并且有许多模式(在数千个范围内)需要检查,使得过程非常慢,因为同一文件的多次读取将是涉及。
有没有办法快速做到这一点?
答案1
可能awk
是这里最快的 shell 工具。你可以尝试:
awk "/$regex1/ { ++r1 }
/$regex2/ { ++r2 }"'
END { print "regex1:",r1 "\nregex2:",r2 }' <infile
当然,如果您需要perl
像您的问题一样使用正则表达式,那么确实perl
是唯一的答案。但是,awk
确实使用扩展表达式(例如grep -E
)而不是基本表达式。
答案2
我能想到的最快的解决方案是柔性。以下是未经测试的骨架:
%{
int count[1000];
%}
%%
regex0 {count[0]++; }
regex1 {count[1]++; }
...
.|\n {}
%%
int main(){
yylex();
// printf the counts;
}
flex 在优化自动机方面做得非常好,并生成快速的 C 代码。
如果正则表达式发生变化,您必须重新编译它......
编辑:如果您实施并尝试任何解决方案,看看时代会很有趣。
答案3
如果可以选择 Python,您可以首先内存映射文件,然后对其运行增量正则表达式搜索,利用命名组计算模式出现次数。该解决方案可以容忍大文件大小
from collections import Counter
import re, mmap, contextlib
c = Counter()
with open('data_file', 'r+') as f:
with contextlib.closing(mmap.mmap(f.fileno(), 0)) as data:
for m in re.finditer(r'(?P<pat1>regex1)|(?P<pat2>regex2)|(?P<pat3>regex3)',data):
c.update(k for (k, v) in m.groupdict().iteritems() if v)
print c.most_common()
[('pat3', 3), ('pat1', 2), ('pat2', 2)]