여러 정규식을 검색해야 하고 각 정규식에 대한 일치 항목 수를 계산해야 하는 파일이 있다고 가정해 보겠습니다.
따라서 다음 패턴을 결합할 수 없습니다.
grep -Po '{regex_1}|{regex_2}|...|{regex_n}' file | wc -l
...각 정규식의 발생 횟수가 필요하기 때문입니다.
분명히 할 수 있습니다:
occurences[i]=$(grep -Po "${regex[i]}" file | wc -l)
...하지만 불행하게도 발견된 파일은 매우 클 수 있고(>1GB) 확인해야 할 패턴이 많아(수천 개 범위) 동일한 파일을 여러 번 읽어야 하므로 프로세스가 매우 느려집니다.
이 작업을 빠르게 수행할 수 있는 방법이 있나요?
답변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)]