grep: 어떤 *패턴*이 일치하는지, 어떤 텍스트가 일치하지 않나요?

grep: 어떤 *패턴*이 일치하는지, 어떤 텍스트가 일치하지 않나요?

로컬 로그 검사 규칙을 유지할 때 어떤 규칙이 더 이상 사용되지 않는지 아는 것이 좋습니다. 나는 이것을 수행하는 합리적으로 효율적인 방법을 찾으려고 노력하고 있습니다.

즉, 상당히 많은 수의 GNU grep 확장 regexp( grep -E) 패턴(약 700개)과 많은 양의 syslog 출력(수십억 줄)이 주어지면 약 700개 패턴 중 어느 패턴이 일치하는지 확인하고 싶습니다.전혀시스템 로그 라인 수. 더 좋은 방법은 각 패턴이 일치하는 syslog 행 수를 알아내는 것입니다.

가장 확실한 방법은 grep -c -E "$pattern" «massive-logfile»각 패턴마다 한 번씩 약 700번 정도 실행하는 것입니다. 그러나 이는 특히 RAM에 많은 수의 로그 파일을 저장할 수 없는 경우 비효율적으로 보입니다.

이를 수행하는 효율적인 방법이 있습니까?

답변1

awk's'와 매우 유사한 who 정규식을 사용할 수 있습니다 .grep -E

awk '!patterns_read{patterns[$0]; next}
     {for (p in patterns) if ($0 ~ p) c[p]++}
     END {
       for (p in patterns) printf "'%s' was matched %d times\n", p, c[p]
     }' patterns patterns_read=1 log files

답변2

각 모드에 대해:

if ! grep -q "$pattern" /path/to/input; then
    echo "/${pattern}/ not found."
fi

AFAIK 그게 유일한 방법입니다. 한 번에 여러 패턴을 검색하는 경우에만 일치했다는 것을 알 수 있기 때문입니다.적어도그들 중 하나. 논리적 OR이 많은 경우(예: /(needle|pin)/각 OR에서 반복)그것들하지만 여전히 한 번에 하나의 표현식을 테스트해야 합니다.

답변3

RE의 복잡성에 따라 Python(테스트되지 않음)과 같은 언어를 사용할 수 있습니다.

#! /usr/bin/env python3
import re, sys
res = ["re1", "re2", ... ]  # or read from a file
recs = [re.compile(r) for r in res]
matches = {}
for line in sys.stdin:
    for r in recs:
        if r.match(line):
            matches[r] += 1
for r in matches:
    if matches[r] == 0:
        print(r.pattern)

물론, 정규식에 Python의 고급 정규식 지원이 문자 그대로 이해하지 못할 수 있는 문자열이 포함된 경우에는 작동하지 않습니다. 출력을 제공하여 많은 작업을 제거할 수 있습니다 grep(이후 정규식 일치가 없는 행을 제거했습니다).

답변4

perl -lne '
   # read in the patterns into a hash
   @ARGV and $h{$_}=s|/|\\/|gr,next;

   # delete pattern if matched, so we wont have to
   # expend efforts on it for the subsequent lines
   while (my($pat) = each %h) {
      delete $h{$pat} if /$h{$pat}/;
   }

   # what remains are those that did not match
   END {
      print "These patterns did not match:";
      print for keys %h;
   }
' patterns_file log_file

관련 정보