Python中的贪婪与非贪婪匹配

时间:2010-08-01 16:04:44

标签: python regex greedy non-greedy

请帮我发现这是否是Python(2.6.5)中的错误,是我写正则表达式的能力,还是我对模式匹配的理解。

(我接受一个可能的答案是“升级你的Python”。)

我正在尝试解析Yubikey令牌,允许使用可选的附加功能。

当我使用此正则表达式来匹配没有任何可选附加项的令牌(即仅包含与两个捕获组匹配的内容)时,匹配失败:

r'^\t?[^a-z0-9]?([cbdefghijklnrtuv1-8]{0,32})\t?([cbdefghijklnrtuv1-8]{32})\t?\r?\n?$'

但是,如果我让第一组非贪婪:

r'^\t?[^a-z0-9]?([cbdefghijklnrtuv1-8]{0,32}?)\t?([cbdefghijklnrtuv1-8]{32})\t?\r?\n?$'

成功。

所以,好吧,它正在运作,但我认为这两个正则表达式之间最终结果的唯一区别就是性能。

Expresso和Regex Coach都喜欢这两种模式。

我错过了什么?


以下是我正在测试的两个字符串。

没有可选的额外内容(可能失败的附加内容):

"vvbrentlnccnhgfgrtetilbvckjcegblehfvbihrdcui"

使用可选附件(到目前为止没有失败;实际标签在此处显示为“_”):

"_!_8R5Gkruvfgheufhcnhllchgrfiutujfh_"
"_!1U4Knivdgvkfthrd_brvejhudrdnbunellrjjkkccfnggbdng_"

我尝试使用Alex Martelli的建议重现它,并且它在原始Python环境中没有失败,所以我将重新访问我的代码(我实际上是在攻击yubikey-python);我会在一天左右的时间里回复。


我向大家道歉。我无法重现这个问题。当它发生时,我正在通过getpass阅读输入;我怀疑意外的外键击中了阻碍。

我将结束这个问题。如果提出问题的人希望取消投票,这是公平的。

非常抱歉。

2 个答案:

答案 0 :(得分:3)

我建议使用yubikey-python进行与yubikey的Python接口 - 但这是一个侧面(并且是严格实用的)问题; - )。

理论上,不应该选择贪婪和非贪婪之间的选择导致RE在一种情况下匹配而在另一种情况下失败 - 它应该只影响匹配的内容(并且当你提到性能时),而不是是否匹配成功,因为RE应该为此目的回溯。

问题是,我无法重现问题 - 我手边没有yubikey,this file中的测试显示两个RE的匹配/不匹配行为之间没有差异。

你能否发布一些失败的例子(其中一个匹配而另一个不匹配),理想情况下是通过编辑你的问题,所以我可以重现问题并尝试将其降低到最低限度?听起来可能存在RE错误,但是如果没有可重复的情况,我无法检查它是否以及何时被修复,已经报告或者是什么。谢谢!

编辑 OP现在发布了一个失败的示例,但我仍然无法重现:

$ py26
Python 2.6.5 (r265:79359, Mar 24 2010, 01:32:55) 
[GCC 4.0.1 (Apple Inc. build 5493)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import re
>>> r1 = re.compile(r'^\t?[^a-z0-9]?([cbdefghijklnrtuv1-8]{0,32})\t?([cbdefghijklnrtuv1-8]{32})\t?\r?\n?$')
>>> r2 = re.compile(r'^\t?[^a-z0-9]?([cbdefghijklnrtuv1-8]{0,32}?)\t?([cbdefghijklnrtuv1-8]{32})\t?\r?\n?$'
... )
>>> nox="vvbrentlnccnhgfgrtetilbvckjcegblehfvbihrdcui"
>>> r1.match(nox)
<_sre.SRE_Match object at 0xcc458>
>>> r2.match(nox)
<_sre.SRE_Match object at 0xcc920>
>>> 

即,匹配在两种情况下都成功,因为它应该 - 并且与OP正在使用的2.6.5 Python版本完全相同。 OP,请在您的平台上显示这个简单命令序列的结果,并告诉我们该平台究竟是什么,因为它看起来像一个奇怪的平台依赖的bug ...谢谢!

答案 1 :(得分:0)

你是对的:简单地从贪婪切换到非贪婪量词不应该导致正则表达式停止工作。它可以改变正则表达式匹配(或不匹配)的速度,它匹配的多少,以及哪些部分被捕获在哪些组中,这就是全部。

(以下“解决方案”不适用,但问题仍然没有表明正在执行不区分大小写的匹配,因此我将保留它。)

你的问题是带有可选附加功能的字符串中也包含大写字母,而你的正则表达式只允许使用小写字母。在正面或正则表达式上粘贴(?i),它就可以正常工作。