たとえば、ファイルがあり、そのファイルで複数の正規表現を検索し、各正規表現の一致数をカウントする必要があるとします。
したがって、パターンを組み合わせることができません。
grep -Po '{regex_1}|{regex_2}|...|{regex_n}' file | wc -l
...各正規表現の出現回数が必要なため。
私は明らかにできました:
occurences[i]=$(grep -Po "${regex[i]}" file | wc -l)
...しかし残念ながら、検出されたファイルは非常に大きく(> 1 GB)、チェックするパターンが多数(数千の範囲)あるため、同じファイルを複数回読み取るとプロセスが非常に遅くなります。関与。
これを迅速に行う方法はありますか?
おそらくawk
がここで最速のシェルツールになるでしょう。あなたは試すことができます:
awk "/$regex1/ { ++r1 }
/$regex2/ { ++r2 }"'
END { print "regex1:",r1 "\nregex2:",r2 }' <infile
もちろん、質問のようにPerl
正規表現を使用する必要がある場合は、実際にはPerl
が唯一の答えです。ただし、awk
は、基本的な式ではなく、拡張式(grep -E
など)を使用します。
私が考えることができる最速の解決策はflexです。以下は、テストされていないスケルトンです。
%{
int count[1000];
%}
%%
regex0 {count[0]++; }
regex1 {count[1]++; }
...
.|\n {}
%%
int main(){
yylex();
// printf the counts;
}
flexは、オートマトンの最適化において非常に優れた仕事をし、高速なCコードを生成します。
Regexが変更された場合は、再コンパイルする必要があります...
[〜#〜] edit [〜#〜]:いずれかのソリューションを実装して試してみると、時代を見るのが面白いでしょう。
Pythonがオプションの場合、最初に memory-map ファイルを実行してから、 名前付きグループ)を利用して、ファイルに対して増分正規表現検索を実行できます。 パターンの発生をカウントします。このソリューションは大きなファイルサイズに耐性があります
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)]