亚历山大的回答 https://stackoverflow.com/a/25943443/20938可能已经足够好了,但我会这样做:
(?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
and doesn't find a Error
在下一个之前End
,它立即失败。
下面是一个 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()
}
UPDATE:我刚刚意识到我不应该添加Error
分支到第二个交替。我的正则表达式仅匹配那些Start..End
包含的块Error
恰好一次,这可能太具体了。这个版本匹配一个块at least出现一次Error
in it:
(?si)\bStart\b(?>(?:(?!\b(?:Start|End|Error)\b).)*)\bError\b(?>(?:(?!\b(?:Start|End)\b).)*)\bEnd\b