2014-03-28 19 views
1

我想制定一個正則表達式能夠匹配任何特定的模式。然後,正則表達式將繼續查找其他模式直到字符串結束,但在某些情況下,模式不會出現,匹配將失敗。現在,我被困在:Python的正則表達式:如何匹配任何特定的字符串,並避免回溯失敗時

.*?PATTERN 

的問題是,在該字符串不存在的情況下,這需要太多的時間,由於回溯法。爲了縮短這個,我試圖模仿使用正向前查找原子團在此線程解釋(順便說一句,我使用的python-2.7 re模塊): Do Python regular expressions have an equivalent to Ruby's atomic grouping?

所以我寫了:

(?=(?P<aux1>.*?))(?P=aux1)PATTERN 

當然,當STRING不存在時這比以前的版本更快,但麻煩是,它不再與STRING相匹配。將everyhing與字符串的末尾匹配,並且之前的狀態在lookahead之後被丟棄。

所以問題是,有沒有辦法像.*?STRING這樣的比賽,並且當比賽不存在時能夠更快地失敗?

+0

正則表達式中的STRING是哪裏?我不能完全按照你的例子。 –

+0

你好。我正在尋找的模式是「src =」,我需要。*?之前因爲可能有幾個變量字段,我想忽略:^(?:(?:\ d {4} - \ d {2} - \ d {2} \ s + \ d \ d:\ d \ d :\ d \ d)|(?:?\ W {3} \ S + \ d {1,2} \ S \ d \ d:\ d \ d:\ d \ d))\ S + ID =(P S +)s + sn =(?P \ S +)\ s + time = \「(?P \ d {4} - \ d {2} - \ d {2} \ s + \ d {2 }(?:: \ s +)\ d {2}(?:: | \ s +)\ d {2} [^「] *)\」\ s + fw =(?P \ S + pri =(?P \ d)\ s +(?:\ S + \ s +)m =(?P \ d +)\ s +。*?src =(?P [^:\ s] +)(?: :(?P [^:\ s] *)\ S *)?\ s + dst =(?P [^:\ s] +)(?: :(?P [^:\ s] * )\ S *)?\ s + proto =(?P [^ /] +)。*?Category = \「(?P [^ \」] +)。* $ – Ilopez

+0

這是一種線我正在解析: May 18 12:47:21 id = firewall sn = XXXXXXX time =「2012-05-18 19:47:42 UTC」fw = xxx.xxx.xxx。 xxx pri = 6 c = 1024 m = 97 n = 696201 src = xxx.xxx.xxx.xxx:xxxx:X0:xxxxxxxx dst = xxx.xxx.xxx.xxx:80:X2:xxxxxx.com proto = tcp/http op = GET sent = 1274 rcvd = 8355 result = 0 dstname = www.xxxx.com arg = xxxxxxxxxxxxx appcat =「xxxxx」appid = xxx code = 31 Category:「Web Communications」 – Ilopez

回答

0

一正則表達式的解決方案

^(?=(?P<aux1>(?:[^P]|P(?!ATTERN))*))(?P=aux1)PATTERN 

說明

你想用固化分組是這樣的:(?>.*?)PATTERN,對不對?這不起作用。問題是,你不能在原子分組結尾使用懶惰的量詞:AG的定義是,一旦你在它之外,正則表達式不會在裏面回溯。

因此,正則表達式引擎將匹配.*?,由於懶惰,它會跨出組來檢查下一個字符是否爲P,如果不是,它將無法在組內回溯到匹配.*內的下一個字符。

Perl中通常使用的結構是這樣的結構:(?>(?:[^P]|P(?!ATTERN))*)PATTERN。這樣,相當於.*(這裏是(?:[^P]|P(?!ATTERN)))不會「吃掉」想要的模式。

在我看來,這種模式更容易理解爲佔有量詞,它們僅適用於這些場合:(?:[^P]|P(?!ATTERN))*+PATTERN

翻譯你的解決方法,這將導致上述正則表達式(添加^,因爲你應該錨定正則表達式,無論是字符串的開始或另一個正則表達式)。

+0

非常感謝!這完成了這項工作。不幸的是,python re模塊在這一刻不支持AG,也沒有支持量化符,我無法改變它的正則表達式模塊。 – Ilopez

+0

不客氣,很高興我能提供幫助。不要忘記將解決問題的解決方案標記爲「已接受」來解決問題,而且您還是很好的! – Robin

0

Python文檔包含re.search()re.match()函數http://docs.python.org/2/library/re.html#search-vs-match之間差異的簡要概述。特別是,下面的引用是相關的:

有時候你會試圖繼續使用re.match(),並且只是將。*添加到RE的前面。抵制這種誘惑並改用re.search()。正則表達式編譯器對RE進行了一些分析,以加速尋找匹配的過程。一個這樣的分析就是指出比賽的第一個字符必須是什麼;例如,從Crow開始的模式必須匹配以'C'開始。分析讓引擎快速瀏覽字符串尋找起始字符,只有在找到'C'時才嘗試完整匹配。

添加*打敗了這個優化,需要掃描到字符串的末尾,然後回溯找到其餘RE的匹配。使用re.search()來代替。

在你的情況,這將是最好定義模式簡稱爲:

pattern = re.compile("PATTERN") 

然後調用pattern.search(...),當未找到模式,不會走回頭路。

+0

Hi Brett。我已經在使用re.search了,它只是。*?PATTERN是更大的正則表達式的一部分。我想我應該爲這個問題添加一條評論來澄清這一點。謝謝! – Ilopez

1

你可以嘗試使用split

如果結果是長度爲1的你有沒有比賽。如果你得到兩個或更多,你就知道第一個是第一個匹配。如果將分組限制爲一個分組,則會將後續匹配短路:

"HI THERE THEO".split("TH", 1) # ['HI ', 'ERE THEO'] 

結果的第一個元素是匹配的。

+0

嗨保羅。不幸的是,我無法改變已經使用re.search的代碼,但這是一個很好的技巧。謝謝! – Ilopez

相關問題