Python-Script在通过正则表达式时停止工作

时间:2011-03-25 14:46:03

标签: python regex search

我有一个大文本文件,我使用for ... in语句逐行处理它:

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] <oyalcin@aaa.com> -> <acanli@aaa.com.tr>,<aeren@aaa.com.tr>,<aergul@aaa.com.tr>,<dalp@aaa.com.tr>,<faks@aaa.com.tr>,<fkonyali@aaa.com.tr>,<hozsoy@aaa.com.tr>,<makcan@aaa.com.tr>,<mengin@aaa.com.tr>,<mervekayabasi@aaa.com.tr>,<muhasebe@aaa.com.tr>,<okkesgol@aaa.com.tr>,<personel@aaa.com.tr>,<skazanci@aaa.com.tr>,<sumur@aaa.com.tr>,<tkececioglu@aaa.com.tr>,<ydemirci@aaa.com.tr>,<abalcin@aaa.com>,<adanisti@aaa.com>,<akaramanli@aaa.com>,<aozsahin@aaa.com>,<benalin@aaa.com>,<cgokburun@aaa.com>,<dkilinc@aaa.com>,<gleblebici@aaa.com>,<hsannan@aaa.com>,<iziyan@aaa.com>,<kcspetrol@aaa.com>,<malakus@aaa.com>,<maltuntas@aaa.com>,<mdelice@aaa.com>,<mguclu@aaa.com>,<mkocyigit@aaa.com>,<mokuducu@aaa.com>,<mtabar@aaa.com>,<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:

我已经在另一个文件上尝试了这个脚本,但它运行正常。它也适用于这个文件,直到这一行出现。可能导致这个问题的原因是什么?

2 个答案:

答案 0 :(得分:4)

可以编写需要非常长时间匹配或失败的正则表达式。你写的只是这样一个正则表达式。基本上,只要您看到*+嵌套在另一个*+内,就会非常害怕。

我认为你的问题可能是:

(<\S*>,)*

就它本身而言,<\S*>将匹配下一个空格的所有内容,然后当完整模式无法匹配时,它会尝试缩短匹配,然后外部*表示它会尝试许多不同的组合匹配20封电子邮件,后跟无,或19后跟1,或18后跟2,或18后跟1后跟1.你在那里有失控的组合。

我建议您尝试使用与终止字符不匹配的模式替换所有\S次出现。例如可以减少问题的<[^> ]*>[^, ]*,

答案 1 :(得分:0)

我不是Python正则表达式的专家,而是一些一般性的观察

你有很多锚点,所以贪婪的量词几乎无处不在,除了在一个地方。

(<\S*>,)*这不符合你的想法。

本质上,该组只会被执行0或1次,所以它实际上是(<\S*>,)? 而且,比赛将如下进行:

<aergul@aaa.com.tr>, ... <dalp@aaa.com.tr>,
^       ^^^^^^^^^^^^^^^^^^^^^^^^^^^          ^^
<               \S*                          >,

它不会使用任意数量的捕获组进行捕获 它在功能上等同于(并且写得更好):

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

我已使用您提供的数据样本测试了(<\S*>,)*。它在Perl中运行正常。但我只能假设你的数据超出你所展示的范围。只需在一个表达式中实现捕获所有内容到下一个大锚>, Message-ID:

可以重写为:
(<\S*?>,)*只保留序列中的最后一个<>,,其中括号仅作为非捕获分组进行相关。