grep:匹配哪些*模式*,而不是哪个文本?

grep:匹配哪些*模式*,而不是哪个文本?

在维护本地日志检查规则时,最好知道哪些规则不再使用。我正在尝试找到一种相当有效的方法来做到这一点。

换句话说,给定相当大量的 GNU grep 扩展 regexp ( grep -E) 模式(大约 700 个)和大量 syslog 输出(数十亿行),我想确定其中哪一个 ≈700模式匹配没有任何系统日志行的数量。更好的是找出每个模式匹配的系统日志行数。

最明显的方法是运行grep -c -E "$pattern" «massive-logfile»约 700 次,每个模式运行一次。但这似乎效率低下,尤其是在 RAM 无法容纳大量日志文件的情况下。

有没有一些有效的方法来做到这一点?

答案1

您可以使用与'sawk非常相似的 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 实际上是唯一的方法,因为如果您一次搜索多个模式,您只会知道您已经匹配至少其中之一。如果您有很多逻辑或(例如/(needle|pin)/,从迭代每个那些排列,但您仍然需要一次测试一个表达式。

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

相关内容