我认为我对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)测试它,它也失败了。
答案 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)
因此,该组是空的,因为左侧匹配,这就是findall给你的。
要修复,请使您的群组无法捕捉:
entrepreneur|business\s(?:plan|model)
现在,没有组findall
返回主表达式匹配的内容。