正则表达式:如何访问一个组的多个匹配?

106

我正在编写一个相当复杂的正则表达式。 表达式的一部分匹配诸如'+a','-57'等字符串。+或-后面跟着任意数量的字母或数字。 我想匹配0个或多个匹配此模式的字符串。

这是我想出来的正则表达式:

([\+-][a-zA-Z0-9]+)*

如果我用这个模式搜索字符串“-56+a”,我期望能够得到两个匹配项:

+a 和 -56

但是,实际上只返回了最后一个匹配项:

>>> m = re.match("([\+-][a-zA-Z0-9]+)*", '-56+a')
>>> m.groups()
('+a',)

查看Python文档后,我发现:

如果一个组匹配了多次,只有最后一次匹配是可访问的:

>>> m = re.match(r"(..)+", "a1b2c3")  # Matches 3 times.
>>> m.group(1)                        # Returns only the last match.
'c3'
所以,我的问题是:如何访问多个组匹配?
2个回答

86

从你的正则表达式中去掉*(这样它就只匹配模式的一个实例)。然后使用re.findall(...)re.finditer(参见这里)返回所有匹配项。

听起来你基本上正在构建一个递归下降解析器。对于相对简单的解析任务,手动完成是非常常见和完全合理的。如果你有兴趣使用库解决方案(例如,如果你的解析任务可能在以后变得更加复杂),可以看看pyparsing


感谢您的回复。问题在于我提出的表达式只是更长表达式的一部分。我正在尝试对用户输入的字符串进行标记化处理。我认为我可能需要采用“分而治之”的方法,将包含此表达式部分所识别的组的字符串部分分离出来,然后像您建议的那样应用re.findall。再次感谢您的帮助! - Tom Scrace
值得注意的是,re.findall(pattern, string) 将在字符串中查找模式的所有出现,即使这些出现是不连续的。也就是说:re.findall('a.', 'axayaz') == re.findall('a.', '--ax---ay-----az-------') == ['ax', 'ay', 'az'] - Adeel Zafar Soomro
2
是的,不幸的是,在我的情况下,字符串中的位置是相关的。字符串的一个部分中的“+a”可能在另一个部分中意味着完全不同的东西。谢谢。 - Tom Scrace
@Tom:我已经在答案中添加了一些更高级别的链接。如果这个回答解决了你的问题,请点赞(绿色勾号/向上箭头)标记此问题为已解决。 - phooji
谢谢你分享这些链接,phooji。非常有趣。我已经标记了你的答案为被接受的。谢谢大家! - Tom Scrace

50

regex 模块 通过添加 .captures 方法来解决这个问题:

>>> m = regex.match(r"(..)+", "a1b2c3")
>>> m.captures(1)
['a1', 'b2', 'c3']

5
这个答案比目前被接受的回答更简单地解决了我的问题。未来regex模块也将取代Python中的re模块。 - Rubinous
4
这是什么黑暗魔法! - Kwame

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接