grep 查找多个正则表达式,并计算出现次数

grep 查找多个正则表达式,并计算出现次数

假设我有一个文件,必须在其中搜索多个正则表达式,并且必须计算每个正则表达式的匹配数。

因此,我无法组合这些模式:

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)]

相关内容