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
分支到第二交替。我的正则表达式只匹配那些只包含Error
的Start..End
块,这可能太具体。这个版本的块匹配以至少一个在它的Error
发生:
(?si)\bStart\b(?>(?:(?!\b(?:Start|End|Error)\b).)*)\bError\b(?>(?:(?!\b(?:Start|End)\b).)*)\bEnd\b
很好的回答!不过,由于效率因素,我必须将对号交给Alan。再次感谢您的回答! – 2014-09-20 01:08:29