这是Python正则表达式中的错误吗?

时间:2014-05-22 22:22:45

标签: python regex

我认为我对RegEx的态度非常好,我可以阅读最多的任何一个,但这个简单的(在Python中)令我感到困惑。 www.regexpal.com给出了与iPython不同的结果。

data = 'four year entrepreneurial program. Students develop and run a business, gain much needed ...'

m = re.compile('entrepreneur|business\s(plan|model)')

m.findall(data)

给出['']

怎么可能是对的?如果我用parens包装整个东西,它会更好但仍然会返回一个空字符串作为匹配:

m = re.compile('(entrepreneur|business\s(plan|model))')

m.findall(data)

给出[('entrepreneur', '')]

正如我所说,第一个可以在www.regexpal.com上运行。我也用Python(不是iPython)测试它,它也失败了。

3 个答案:

答案 0 :(得分:2)

findall收集群组'值。它不会返回整个匹配的子字符串。你的模式

entrepreneur|business\s(plan|model)

遍历数据字符串,直到找到匹配项。一旦找到匹配(此处为entrepreneurial program...),它就会停在那里并捕获第一组的值(为空)。然后它进一步运行,但没有找到任何匹配。所以最终的结果是一个带有一个空字符串的列表。

要观察类似于regexpal的行为,请将整个表达式括起来并使其他组可选:

>>> re.findall(r'(entrepreneur|business\s(?:plan|model))', data)
['entrepreneur']

答案 1 :(得分:1)

问题是括号。他们创建了一个捕获组,其示例字符串是不匹配的(模式的未组合entrepreneur部分匹配)。如果模式中有任何组,re.findall将返回捕获组结果的元组,这就是为什么你得到一个空字符串。在代码的第二个版本中,您有两个组,第一个版本涵盖整个模式,而第二个版本仅覆盖plan|model部分(不匹配)。

如果您使用非捕获组((?:X))进行plan|model替换,您可能会得到您期望的结果(文字"entrepreneur"),如{{1}如果没有捕获组,则返回整个匹配的文本。

尝试:re.findall

答案 2 :(得分:1)

这就是捕获组如何使用findall

  

re.findall(pattern, string, flags=0)

     

返回字符串中pattern的所有非重叠匹配,作为字符串列表。字符串从左向右扫描,匹配为   按顺序返回。如果一个或多个组存在于   模式,返回组列表;这将是一个元组列表,如果   模式有多个组。空匹配包含在   结果,除非他们触及另一场比赛的开始。

您在交替的右侧有一个捕获组,但是替换的左手侧与您的字符串匹配。

entrepreneur|business\s(plan|model)

Regular expression visualization

Debuggex Demo

因此,该组是空的,因为左侧匹配,这就是findall给你的。

要修复,请使您的群组无法捕捉:

entrepreneur|business\s(?:plan|model)

现在,没有组findall返回主表达式匹配的内容。