我有一个大文本文件,我使用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:
我已经在另一个文件上尝试了这个脚本,但它运行正常。它也适用于这个文件,直到这一行出现。可能导致这个问题的原因是什么?
答案 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*?>,)*
只保留序列中的最后一个<>,
,其中括号仅作为非捕获分组进行相关。