【问题标题】:regex onigurama Negative lookbehind not working正则表达式 onigurama 负向后看不起作用
【发布时间】:2016-11-28 10:59:43
【问题描述】:

我正在尝试使用 onigurama 正则表达式库(在 Logstash 中)使用否定的后视来捕获日志文件中的一行,但它似乎仍然与它不应该匹配的行匹配。我试图只匹配顶级异常,而不是以 Caused By:

开头的异常

有人帮我写了这个

在 Rubular 上测试 http://rubular.com/r/N3AzySNHiS

经过测试的正则表达式

^(?<!Caused by: ).*?Exception

(?<!^Caused by: ).*?Exception

消息:

2016-11-15 05:19:28,801 ERROR [App-Initialisation-Thread] appengine.java:520 Failed to initialize external authenticator myapp Support Access || appuser@vm23-13:/mnt/data/install/assembly app-1.4.12@cad85b224cce11eb5defa126030f21fa867b0dad
java.lang.IllegalArgumentException: Could not check if provided root is a directory
    at com.myapp.jsp.KewServeInitContextListener$1.run(QServerInitContextListener.java:104)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.nio.file.NoSuchFileException: fh-ldap-config/
    at com.upplication.s3fs.util.S3Utils.getS3ObjectSummary(S3Utils.java:55)
    at com.upplication.s3fs.util.S3Utils.getS3FileAttributes(S3Utils.java:64)

Logstash 结果

"exception" => "Caused by: java.nio.file.NoSuchFileException"

【问题讨论】:

  • 试试^(?!Caused by: ).*?Exception,或^(?!Caused by:)(?&lt;exception&gt;.*?Exception)
  • 感谢Wiktor的回复,第一个返回"exception" =&gt; " at java.lang.Thread.run(Thread.java:745)\nCaused by: java.nio.file.NoSuchFileException",第二个返回2个结果` "exception" => [ [0] " at java.lang.Thread.run(Thread.java :745)\n引起:java.nio.file.NoSuchFileException",[1]" at java.lang.Thread.run(Thread.java:745)\n引起:java.nio.file.NoSuchFileException"`跨度>
  • 我怀疑有一些设置使正则表达式中的. 符号与换行符匹配。或者其他一些选项,如忽略空格是 ON。请检查是否在任何地方打开了多行模式。另外,一个好主意是检查^(?!Caused\ by:)(?&lt;exception&gt;[^\r\n]*?Exception) regex
  • 谢谢@WiktorStribiżew!最后一个正则表达式就像一个魅力,但返回了 2 个结果 "exception" =&gt; [ [0] "com.fredhopper.frontend.view.ViewCreationException", [1] "com.fredhopper.frontend.view.ViewCreationException" 它是否以某种方式匹配同一行两次?
  • 不,再次,这是我们上次讨论的内容,我不知道什么设置可能会返回两次捕获的文本。

标签: regex logstash regex-lookarounds logstash-grok oniguruma


【解决方案1】:

您的 Logstach 环境中似乎设置了一些其他选项。根据我的测试,我怀疑启用了“详细”或“忽略空格”选项。此外,要排除. 的任何其他问题(可能会重新定义以匹配换行符),您可以使用明确的[^\r\n](任何字符不是\r\n):

^(?!Caused\ by:)(?<exception>[^\r\n]*?Exception)
          ^^                 ^^^^^^^

转义的空格将始终匹配单个常规空格。

【讨论】:

  • 再次感谢维克托!工作得很好,感谢您的解释
  • 是的,谢谢 Wiktor,顺便说一下,我们设法通过删除 ? 来消除双重结果,所以最终的正则表达式是 ^(?!Caused\ by:)([^\r\n]*?Exception)
  • 这意味着 named_captures_only 被设置为 false。如果是默认值 (true),则仅输出命名的捕获组。
【解决方案2】:

注意:我在整个答案中假设问题中显示并在下面重复的 2 个单独的日志行不包含换行符,并且已通过 logstash 中的多行编解码器插件处理或以某种方式删除。

TL;DR 使用负向回溯的解决方案

如果事后给予适当的锚点,消极的目光就会起作用。看看这两行,这会很好:

^(?&lt;!Caused by: )java.*Exception

注意:它可能只是^(?&lt;!Caused by: )j.*Exception,但我认为java 使它更具可读性。

示例代码问题说明

给定正则表达式的问题:^(?&lt;!Caused by: ).*?Exception(?&lt;!^Caused by: ).*?Exception 是不情愿的 *? 量词,它允许匹配 0 次或更多次。现在正如answer 中所解释的那样,正则表达式引擎从字符串的开头开始并向左移动以写入。尽可能少的字符数(因为它是不情愿的)只不过是引擎无法匹配Exception,然后它在Exception(“回溯”)向左写入之前逐渐尝试匹配任何内容(.)。

因此,正则表达式引擎一直尝试一次匹配一个字符(从左到右),直到在消耗完之后找到Exception。因此字符串

Caused by: java.nio.file.NoSuchFileException: fh-ldap-config/ at com.upplication.s3fs.util.S3Utils.getS3ObjectSummary(S3Utils.java:55) at com.upplication.s3fs.util.S3Utils.getS3FileAttributes(S3Utils.java:64)

匹配,因为引擎已经消耗了直到Exception 的所有内容,并且Caused by: 没有出现在此匹配之前。本质上,.*? 已经消耗了负面后向寻找的Caused by:

深入了解

要了解正则表达式引擎对环视的实际作用,我建议查看answer

我认为量词和环视很容易被抓住,一般来说,我认为环视需要锚定具体的东西(不是.)。为了理解我的意思,让我们看看给定正则表达式与贪婪的 * 量词的细微变化。正则表达式 ^(?&lt;!Caused by: ).*Exception 也匹配引用的字符串。

原因是贪婪的* 限定符首先消耗整个字符串,然后从右到左回溯,如上面第一个链接答案中所述。出于同样的原因(但从另一方面),一旦引擎匹配Exception,它就会保存从字符串开头到Exception 的所有内容。然后它查看它所消耗的内容,并没有找到 Caused by: 并成功匹配该字符串。

总而言之,作为一般规则

在使用贪婪或不情愿的量词时始终锚定环视。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多