2

我正在尝试使用 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"
4

2 回答 2

1

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

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

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

于 2016-11-28T12:50:00.340 回答
0

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

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

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

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

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

示例代码问题说明

给定正则表达式的问题:^(?<!Caused by: ).*?Exceptionand(?<!^Caused by: ).*?Exception是不情愿的*?量词,它允许匹配 0 次或更多次。现在正如this 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:

深入了解

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

我认为很容易被量词和环视所吸引,并且作为一般规则,我认为环视需要由具体的东西(不是)锚定。.为了理解我的意思,让我们看一下使用贪婪*量词的给定正则表达式的细微变化。正则表达式^(?<!Caused by: ).*Exception也匹配引用的字符串。

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

总之,作为一般规则

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

于 2018-02-09T00:26:39.003 回答