如果在使用正则expression式的开始词之前出现closures词,则在两个词之间find不匹配的词

所以,在通过日志时,我遇到了一个正则expression式困境。

我目前的正则expression式是这样设置的:

(?si)\bStart\b(.*?)\bError\b(.*?)\bEnd\b 

当我遇到像这样的场景时,这很好用:

 stuff happens Start stuff happens Error stuff happens End 

但是也是这样的,如果错误在开始和结束序列之外,

 Start End Error Start End 

有没有办法让正则expression式只抓取#1是像#2场景的存在? 有时在日志中生成的错误不会发生在StartEnd关键字内。 基本上,我需要隔离没有唯一错误代码或名称的特定types的错误,只是在发生错误时将“错误”一词引发到日志中。

就使用的语言而言,并不重要。 AutoIt或Powershell的例子会很酷,但这更像是一个正则expression式的语法问题。 但是,这是在Windows环境中使用(特别是8.1)

Solutions Collecting From Web of "如果在使用正则expression式的开始词之前出现closures词,则在两个词之间find不匹配的词"

亚历山大的回答可能够好,但我会这样做:

 (?si)\bStart\b(?:(?!\b(?:Start|End)\b).)*\bError\b(?:(?!\b(?:Start|End)\b).)*\bEnd\b 

这个正则表达式的主要优点是它失败得更快。 ((?!\bStart\b).)*? 如果有期望的End ,就可以正常工作,但是如果没有匹配的话,还是要一直到下一个Start (如果有的话)或者在文档结束之前放弃比赛。

事实上,你可以更进一步,完全消除回溯:

 (?si)\bStart\b(?>(?:(?!\b(?:Start|End|Error)\b).)*)\bError\b(?>(?:(?!\b(?:Start|End|Error)\b).)*)\bEnd\b 

添加一个Error选项并将该部分封装在一个原子组中意味着如果它找到一个Start并且在下一个End之前没有找到一个Error ,它立即失败。

这是一个PowerShell示例(由RegexBuddy生成):

 $regex = [regex] '(?si)\bStart\b(?>(?:(?!\b(?:Start|End|Error)\b).)*)\bError\b(?>(?:(?!\b(?:Start|End|Error)\b).)*)\bEnd\b' $matchdetails = $regex.Match($subject) while ($matchdetails.Success) { # matched text: $matchdetails.Value # match start: $matchdetails.Index # match length: $matchdetails.Length $matchdetails = $matchdetails.NextMatch() } 

更新:我只是意识到,我不应该添加Error分支到第二轮。 我的正则表达式只匹配那些包含Error Start..End块,只是一次,这可能太具体了。 该版本至少与一个出现Error的块匹配:

 (?si)\bStart\b(?>(?:(?!\b(?:Start|End|Error)\b).)*)\bError\b(?>(?:(?!\b(?:Start|End)\b).)*)\bEnd\b 

PowerShell,使用负面预测,并假设“东西发生”部分从不包含单词“开始”或“结束”:

 $txt = Get-Content file.txt | Out-String $pattern = "(?si)\bStart\b((?!\bEnd\b).)*?\bError\b((?!\bStart\b).)*?\bEnd\b" $regex = New-Object System.Text.RegularExpressions.Regex($pattern) $regex.Matches($txt) 

在这里解释。

好吧,所以当我能够理解被接受的答案是逐步完成的时候,我又回到了这个问题上,这对我来说比对一行中的所有东西都容易理解。 这个替代的答案解释了从原始问题的目标开始到结束的过程,这个目标是按照3个匹配模式进行的,并且确保不会发生不需要的匹配。

第1步 :在添加排除项之前让您的模式工作

 \bStart\b.*\bError\b.*\bEnd\b 

第2步 :放置非捕捉组,检查任何类型的字符(S),同时移动. 在里面。 这些非捕获组(?:.)现在只是占位符,意味着它们将检查任何字符,所以它不会破坏我们已经建立的模式。

 \bStart\b(?:.)*\bError\b(?:.)*\bEnd\b 

第3步 :现在我们要把这些非捕获组放在一个积极的向前看,它里面的非捕获组是一个负面的向前看,所以我们知道,如果它检测到开始,结束,或者除了最后一个错误之外,会提前失败。 如果不打破最小匹配功能,我们无法真正打破这一块。

 \bStart\b(?>(?:(?!\b(Start|End|Error)\b).))*\bError\b(?>(?:(?!\b(Start|End)\b).))*\bEnd\b 

第4步 :现在,只需在开始处添加行匹配过滤器,就可以开始了!

 (?si)\bStart\b(?>(?:(?!\b(Start|End|Error)\b).))*\bError\b(?>(?:(?!\b(Start|End)\b).))*\bEnd\b 

我是一个高度视觉的学习者,所以我分享了一个亲自帮我分解的图表。

在这里输入图像说明