正则表达式 onigurama 负后视不起作用
regex onigurama Negative lookbehind not working
我正在尝试使用 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.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"
您的 Logstach 环境中似乎设置了一些额外的选项。根据我的测试,我怀疑启用了 "verbose" 或 "ignore whitespace" 选项。此外,要排除 .
的任何其他问题(可以重新定义以匹配换行符),您可以使用明确的 [^\r\n]
(任何不是 \r
和 \n
的字符):
^(?!Caused\ by:)(?<exception>[^\r\n]*?Exception)
^^ ^^^^^^^
转义的 space 将始终匹配单个正则 space。
注意:我在整个回答中都假设问题中显示并在下面重复的 2 个单独的日志行不包含换行符,并且已通过 logstash 中的多行编解码器插件进行处理或以某种方式删除。
TL;DR 使用负后视的解决方案
如果事后给它一个合适的锚点,消极的回头看就会起作用。查看这两行,这会很好地工作:
^(?<!Caused by: )java.*Exception
注意:它可能只是 ^(?<!Caused by: )j.*Exception
,但我认为 java
使其更具可读性。
示例代码问题说明
给定正则表达式的问题:^(?<!Caused by: ).*?Exception
和 (?<!^Caused by: ).*?Exception
是不情愿的 *?
量词,它允许某项匹配 0 次或多次。现在正如本 answer 中所解释的那样,正则表达式引擎从字符串的开头开始并向左移动以写入。尽可能少的字符数(因为它不愿意)只不过是引擎无法匹配 Exception
然后它逐渐尝试匹配 Exception
之前的任何内容(.
)("backtracking") 左移书写。
因此,正则表达式引擎一直尝试一次再匹配一个字符(从左到右),直到在消耗完后找到 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:
。
深入了解
要了解正则表达式引擎实际对 lookarounds 做了什么,我建议查看此 answer
我认为很容易被量词和环顾四周所吸引,作为一般规则,我认为环视需要 锚定 一些具体的东西(而不是 .
) .为了理解我的意思,让我们看一下给定正则表达式与贪婪 *
量词的细微变化。正则表达式 ^(?<!Caused by: ).*Exception
也匹配带引号的字符串。
原因是贪婪的 *
限定符首先消耗整个字符串,然后从右向左回溯,如上面第一个链接的答案中所述。出于同样的原因(但从另一方面来说)一旦引擎匹配 Exception
,它就会保存从字符串开头到 Exception
的所有内容。然后它会查看已消耗的内容,但未找到 Caused by:
并成功匹配字符串。
总结,作为一般规则
在使用贪婪或不情愿的量词时始终锚定环视。
我正在尝试使用 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.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"
您的 Logstach 环境中似乎设置了一些额外的选项。根据我的测试,我怀疑启用了 "verbose" 或 "ignore whitespace" 选项。此外,要排除 .
的任何其他问题(可以重新定义以匹配换行符),您可以使用明确的 [^\r\n]
(任何不是 \r
和 \n
的字符):
^(?!Caused\ by:)(?<exception>[^\r\n]*?Exception)
^^ ^^^^^^^
转义的 space 将始终匹配单个正则 space。
注意:我在整个回答中都假设问题中显示并在下面重复的 2 个单独的日志行不包含换行符,并且已通过 logstash 中的多行编解码器插件进行处理或以某种方式删除。
TL;DR 使用负后视的解决方案
如果事后给它一个合适的锚点,消极的回头看就会起作用。查看这两行,这会很好地工作:
^(?<!Caused by: )java.*Exception
注意:它可能只是 ^(?<!Caused by: )j.*Exception
,但我认为 java
使其更具可读性。
示例代码问题说明
给定正则表达式的问题:^(?<!Caused by: ).*?Exception
和 (?<!^Caused by: ).*?Exception
是不情愿的 *?
量词,它允许某项匹配 0 次或多次。现在正如本 answer 中所解释的那样,正则表达式引擎从字符串的开头开始并向左移动以写入。尽可能少的字符数(因为它不愿意)只不过是引擎无法匹配 Exception
然后它逐渐尝试匹配 Exception
之前的任何内容(.
)("backtracking") 左移书写。
因此,正则表达式引擎一直尝试一次再匹配一个字符(从左到右),直到在消耗完后找到 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:
。
深入了解
要了解正则表达式引擎实际对 lookarounds 做了什么,我建议查看此 answer
我认为很容易被量词和环顾四周所吸引,作为一般规则,我认为环视需要 锚定 一些具体的东西(而不是 .
) .为了理解我的意思,让我们看一下给定正则表达式与贪婪 *
量词的细微变化。正则表达式 ^(?<!Caused by: ).*Exception
也匹配带引号的字符串。
原因是贪婪的 *
限定符首先消耗整个字符串,然后从右向左回溯,如上面第一个链接的答案中所述。出于同样的原因(但从另一方面来说)一旦引擎匹配 Exception
,它就会保存从字符串开头到 Exception
的所有内容。然后它会查看已消耗的内容,但未找到 Caused by:
并成功匹配字符串。
总结,作为一般规则
在使用贪婪或不情愿的量词时始终锚定环视。