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