grep은 여러 정규 표현식을 찾아 발생 횟수를 계산합니다.

grep은 여러 정규 표현식을 찾아 발생 횟수를 계산합니다.

여러 정규식을 검색해야 하고 각 정규식에 대한 일치 항목 수를 계산해야 하는 파일이 있다고 가정해 보겠습니다.

따라서 다음 패턴을 결합할 수 없습니다.

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

관련 정보