ChatGPT解决这个技术问题 Extra ChatGPT

Grep 正则表达式不包含字符串

我将正则表达式模式列表传递给 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
你的意思是你有时想匹配一个模式,但其他时候想匹配除特定模式之外的所有东西? (这似乎是一个奇怪的要求,但无论如何)。在那种情况下,为什么不遍历两个不同的模式列表呢?
好吧,我对正则表达式不是很了解;我不想用 grep 表示“已爆炸”,因为我不想知道每个日志记录设备的情况,所以我可以在一个语句中以某种方式 grep “已爆炸”和 !9.10.11.12 吗?
如果你绝对必须在一个声明中做到这一点,那么消极的后视就是要走的路,正如 Neil 所建议的那样。在那里看到我的评论。
根据@Neil 的回答,使用 PCRE 样式的正则表达式匹配和否定的前瞻断言: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 默认假定更多元字符,因此一些转义可能需要从其他匹配的表达式中删除。

b
beerbajay

grep 匹配,grep -v 则相反。如果您需要“匹配 A 但不匹配 B”,通常使用管道:

grep "${PATT}" file | grep -v "${NOTPATT}"

正如我所提到的,这将进入循环的中间,我只是将 PATTERN 传递给 grep,所以我不能像我提到的那样使用“-v”。我只是循环一个 PATTERN 列表并传递给 grep。
您确实可以使用 -v 并且可以循环使用它。也许您需要更具体地了解您的限制,或者您对脚本的工作方式有误解。尝试发布一些代码。
感谢 beerbajay,我在原始帖子中添加了一段代码以提供一些上下文。你明白我现在的意思了吗?
这个答案并不完全正确,但是您几乎写了 beerbajay,我需要重新考虑循环并最终使用 -v。感谢您的指点;)
但是如果 A 由 B 组成呢?换句话说,如果我想匹配没有 A 的行和有 AB 的行怎么办?管道不起作用。
N
Neil
(?<!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 不支持这种类型的正则表达式; $grep -P (?<\!1\.2\.3\.4) test.log -bash: 意外标记 `(' 附近的语法错误
如果正则表达式包含将由 shell 解释的字符,您将需要引用它。
正确引用:grep -P '(?<!1\.2\.3\.4) Has exploded' test.log 请注意,后视仅适用于表达式匹配部分之前的字符,因此如果地址和消息之间存在其他内容,例如 1.2.3.4 FOO Has exploded,则此操作无效。
@TimPietzcker,非常细心。我将把它添加到问题中。另外,请注意,在否定的后视后面有一个 .*,因为他的示例也有它,我想中间可能还有其他文本。
k
krecker
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"    

Z
ZX9

似乎没有人发布所有答案中最好的混合,正则表达式(-E)和匹配反转(-v

grep -Ev 'pattern1|pattern2|pattern3' file

值得注意的是,不需要环顾四周,因此如果您的 grep 版本没有可用的 -P,则此方法有效。