2014-09-19 85 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

相關問題