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で繰り返し)それらしかし、まだ一度に1つの式をテストする必要があります。

答え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

関連情報