Python re.groups不显示所有子组

时间:2016-01-13 16:19:10

标签: python regex

我有一个像'234 3452789 23 901234 ...'这样的字符串。我想提取所有数字。我写了以下正则表达式:

s = '234 3452789 23 901234'
expr = r'^\s*(\d+\s*)+$'
e = re.match(expr, s)
print e.groups()

我希望看到包含所有数字的元组,但实际上这段代码仅打印最新的数字:

('901234',)

问题:我的代码有什么问题,以及如何修复它?

P.S。以下代码效果很好,但我想用任意数量的子字符串解析字符串

expr = r'^\s*(\d+\s*)(\d+\s*)(\d+\s*)(\d+\s*)$'
e = re.match(expr, s)
print e.groups()

5 个答案:

答案 0 :(得分:1)

TL; DR:使用findall()

>>> s = '234 3452789 23 901234'
>>> re.findall('\d+', s)
['234', '3452789', '23', '901234']
  

我希望看到包含所有数字的元组,但实际上这段代码仅打印最新的数字:

('901234',)
     

问题:我的代码有什么问题,以及如何修复它?

这就是match()的工作原理,你无法做任何事情。包含一个组(如您的)的正则表达式只返回一个组。在组右侧指定+* 方式,仅获取最后一场比赛。它以设计的方式工作。

如果您真的想与match()一起使用,regex第三方模块会提供您想要的capturescapturesdict方法。但它不是标准库的一部分。

答案 1 :(得分:1)

我简单的两分钱,回答你的实际问题......为什么要使用正则表达式,为什么不使用

[int(grp) for grp in s.split() if grp.isdigit()]

这会根据空格分隔符将字符串拆分为组,遍历已分隔的组列表,检查它是否为数字,如果是,则将该组推送到列表中。检查是为了确保我们只推回数字。

它(a)更快

python -m timeit -s "import re" "[int(grp) for grp in re.findall('\d+','234 3452789 23 901234')]"
>> 100000 loops, best of 3: 4.14 usec per loop

python -m timeit "[int(grp) for grp in '234 3452789 23 901234'.split() if grp.isdigit()]"
>> 100000 loops, best of 3: 2.99 usec per loop

和(b)基于我从多个讨论中读到的内容......可预测且易于理解。我曾尝试解释re.findallre.searchre.splitre.finditer之间的细微差别。花了我一些时间。如果可以,我的建议尽量避免使用re

答案 2 :(得分:0)

您的第一个代码出了什么问题?

r'^\s*(\d+\s*)+$'正则表达式应匹配起始处的所有数字或空格字符,并且仅捕获最后一位数字符和后面的零个或多个空格,因为您重复捕获组一次或多次。

例如,'(1+)'(1)+正在进行相同的匹配,但两者都会捕获不同的1组。第一个正则表达式捕获所有匹配的1,其中第二个正则表达式仅捕获每个匹配中存在的最后1个。

matchobj.groups()将返回由每个组捕获的所有字符的元组。

答案 3 :(得分:0)

它匹配^...$引起的整个字符串,仅捕获(...)的最后一个匹配项。我认为它不是一个足够强大的用例,尽管有人提交了issue关于允许多个匹配在列表中累积的内容。

groups()的索引是基于正则表达式中捕获组的布局,而不是它所使用的字符串,因此无论如何都不会为每个不同的事件获取一个组。

答案 4 :(得分:-1)

结尾的$会让它选择最后一部分