2014-09-19 138 views
2

因此,通过日志时遇到了正则表达式困境。查找两个单词之间的单词,如果在使用正则表达式之前在开始单词前出现不匹配的单词

我现在正则表达式的设置是这样的:

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

,当我遇到的场景像这样的伟大工程:

stuff happens 
Start 
stuff happens 
Error 
stuff happens 
End 

但也抓住命中这样的,在错误在开始和结束序列之外:

Start 
End 
Error 
Start 
End 

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

就使用的语言而言,无关紧要。 AutoIt或Powershell的例子会很酷,但这更像是一个正则表达式语法问题。然而,这是被Windows环境(特别是8.1)内使用

回答

2

Alexander's answer可能是不够好,但我会做这样的:

(?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分支到第二交替。我的正则表达式只匹配那些只包含ErrorStart..End块,这可能太具体。这个版本的块匹配以至少一个在它的Error发生:

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

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) 

解释here

+0

很好的回答!不过,由于效率因素,我必须将对号交给Alan。再次感谢您的回答! – 2014-09-20 01:08:29

0

好了,所以我回到了这个我能理解什么公认的答案是实现增量片逐片后,这对我来说比一口气中的所有事情都容易理解。这个备选答案解释了从原始问题的目标开始到结束的过程,这个目标是按顺序进行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 

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

enter image description here

相关问题