2011-03-25 33 views
0

我有一個大的文本文件時工作,我通過使用行處理它行了... in語句:Python的腳本停止通過一個正則表達式

f = open(sys.argv[1]) 
for line in f: 

而且我通過一些線正則表達式。但是,當正在通過正則表達式過去了這麼久行我的代碼將停止: 這是行:

Mar 25 09:42:22 2011 amavis[30883]: (30883-10) Passed CLEAN, [95.0.85.202] [95.0.85.202] <[email protected]> -> <[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<[email protected]>,<m... 

這是正則表達式,並在代碼停止的地方:

pattern_clean = re.compile("(\S{3} \d{2} \d{2}\:\d{2}\:\d{2} \d{4}).*CLEAN, (LOCAL)?(\[[.\d]+\])?(\[[.\d]+\])?<(\S*@(\S*))?> -> (<\S*>,)* Message-ID: <(\S*)>, mail_id: (\S*), Hits: (\S*), queued_as: (\S*), (\S*)") 

if pattern_clean.search(line) != None: 

我有試試這個腳本在一個不同的文件上工作好吧。它也適用於這個文件,直到這一行出現。什麼可能導致這個問題?

+0

您是否收到錯誤訊息?如果是這樣,它說什麼? – nmichaels 2011-03-25 14:48:24

+2

是否有可能輸入是python的正則表達式庫的病態?我非常確定python使用backtacking正則表達式系統,所以它可能是你所提供的輸入將其投入到最壞情況的行爲中。該進程是否被鎖定?佔用大量的CPU? – Daenyth 2011-03-25 14:50:01

+0

不,我沒有收到錯誤消息。它只是停在那裏,但不會退出腳本。 CPU使用率也保持在最大值。等級 – Alptugay 2011-03-25 14:51:53

回答

4

編寫正則表達式可能需要非常非常長的時間才能匹配或失敗。你已經寫了這樣一個正則表達式。基本上任何時候你看到*+嵌套在另一個*+非常害怕。

我認爲你的問題可能是:

(<\S*>,)* 

在它自己的,<\S*>會匹配一切到下一個空格,然後在全模式匹配失敗,將盡量縮短比賽下來,然後外部的*意味着它會嘗試很多不同的組合,匹配20封電子郵件,然後是沒有,或19後面跟1,或18跟着2,或18跟着1,然後是1.你有失控的組合。

我建議你嘗試用一種不能匹配終止字符的模式替換所有的\S事件。例如<[^> ]*>[^, ]*,可能會減少問題。

+0

你是對的我簡單地替換(<\S*>,)*([^,] *,)*並且它沒有循環過 – 2011-03-25 15:15:34

+0

(<\S*>,)*我改變了這個正則表達式到((<[^>] *>,)*),現在它工作的很快。感謝所有的幫助。 – Alptugay 2011-04-01 08:15:19

0

我在Python正則表達式的專家,但一些一般性意見

你有足夠的錨,如此貪婪量詞都ok幾乎無處不在,除了在一個地方。

(<\S*>,)*這不會做你認爲它會的。

本質上,該組只會執行0或1次,所以它實際上是(<\S*>,)?
而且,這場比賽將進步是這樣的:

<[email protected]>, ... <[email protected]>, 
^  ^^^^^^^^^^^^^^^^^^^^^^^^^^^   ^^ 
<    \S*       >, 

它不會使用捕捉組任意數量的捕捉。
它在功能上等同於(和更好的寫作)這樣的:

((?:<\S*?>,)+)?

我測試過(<\S*>,)*與您所提供的數據樣本。它在Perl中可以正常工作。但我只能假設你的數據超出你展示的範圍。只要意識到你在一個表達中捕捉到了下一個大錨點>, Message-ID:的所有內容。

它可以重新寫爲:
(<\S*?>,)*剛剛保留在系列賽裏括號只是relavent作爲非捕獲分組的最後<>,