複数の正規表現を検索し、各正規表現の一致数を数える必要があるファイルがあるとします。
したがって、次のパターンを組み合わせることはできません。
grep -Po '{regex_1}|{regex_2}|...|{regex_n}' file | wc -l
...各正規表現の発生回数が必要だからです。
明らかにすることができます:
occurences[i]=$(grep -Po "${regex[i]}" file | wc -l)
...しかし、残念ながら、見つかったファイルは非常に大きくなる可能性があり(> 1 GB)、確認する必要があるパターンが多く(数千の範囲)、同じファイルを複数回読み取る必要があるため、プロセスは非常に遅くなります。
これをすばやく実行する方法はありますか?
答え1
おそらくawk
最速のシェルツールです。あなたは試すことができます:
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)]