我将正则表达式模式列表传递给 grep
以检查系统日志文件。它们通常匹配 IP 地址和日志条目;
grep "1\.2\.3\.4.*Has exploded" syslog.log
它只是一个模式列表,例如我在循环中传递的 "1\.2\.3\.4.*Has exploded"
部分,因此例如我不能传递“-v”。
我很困惑尝试与上述相反,并且不匹配具有特定 IP 地址和错误的行,因此“!1.2.3.4.*已爆炸”将匹配 1.2.3.4 以外的任何内容的系统日志行,告诉我它已爆炸.我必须能够包含一个不匹配的 IP。
我在 StackOverflow 上看到过各种类似的帖子。但是,他们使用我似乎无法使用 grep
的正则表达式模式。谁能为grep
提供一个工作示例吗?
更新:这发生在这样的脚本中;
patterns[1]="1\.2\.3\.4.*Has exploded"
patterns[2]="5\.6\.7\.8.*Has died"
patterns[3]="\!9\.10\.11\.12.*Has exploded"
for i in {1..3}
do
grep "${patterns[$i]}" logfile.log
done
patterns[3]="\!9\.10\.11\.12.*Has exploded"
更改为 patterns[3]="(?<!9\.10\.11\.12).*Has exploded"
和 grep "${patterns[$i]}" logfile.log
更改为 grep -P "${patterns[$i]}" logfile.log
PCRE 默认假定更多元字符,因此一些转义可能需要从其他匹配的表达式中删除。
grep
匹配,grep -v
则相反。如果您需要“匹配 A 但不匹配 B”,通常使用管道:
grep "${PATT}" file | grep -v "${NOTPATT}"
(?<!1\.2\.3\.4).*Has exploded
您需要使用 -P 运行它以获得否定的lookbehind(Perl 正则表达式),因此命令是:
grep -P '(?<!1\.2\.3\.4).*Has exploded' test.log
尝试这个。如果它前面有 1.2.3.4
,它会使用否定的lookbehind 忽略该行。希望有帮助!
grep
不支持环视。除非您使用 Gnu grep
并使用 --P
参数使其使用 PCRE 引擎。
grep -P '(?<!1\.2\.3\.4) Has exploded' test.log
请注意,后视仅适用于表达式匹配部分之前的字符,因此如果地址和消息之间存在其他内容,例如 1.2.3.4 FOO Has exploded
,则此操作无效。
.*
,因为他的示例也有它,我想中间可能还有其他文本。
patterns[1]="1\.2\.3\.4.*Has exploded"
patterns[2]="5\.6\.7\.8.*Has died"
patterns[3]="\!9\.10\.11\.12.*Has exploded"
for i in {1..3}
do
grep "${patterns[$i]}" logfile.log
done
应该是一样的
egrep "(1\.2\.3\.4.*Has exploded|5\.6\.7\.8.*Has died)" logfile.log | egrep -v "9\.10\.11\.12.*Has exploded"
似乎没有人发布所有答案中最好的混合,正则表达式(-E
)和匹配反转(-v
)
grep -Ev 'pattern1|pattern2|pattern3' file
值得注意的是,不需要环顾四周,因此如果您的 grep 版本没有可用的 -P
,则此方法有效。
-v
并且可以循环使用它。也许您需要更具体地了解您的限制,或者您对脚本的工作方式有误解。尝试发布一些代码。