如何在 Python 中获取匹配正则表达式的组名?

新手上路,请多包涵

无论我不知道如何从比赛中找出组名,问题都是非常基本的。让我用代码解释一下:

 import re
a = list(re.finditer('(?P<name>[^\W\d_]+)|(?P<number>\d+)', 'Ala ma kota'))

如何获得 a[0].group(0) 匹配的组名 - 假设命名模式的数量可以更大?

示例被简化以学习基础知识。

我可以反转匹配 a[0].groupdict() 但它会很慢。

原文由 Chameleon 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 638
2 个回答

您可以从已 编译的表达式 中获取此信息:

 >>> pattern = re.compile(r'(?P<name>\w+)|(?P<number>\d+)')
>>> pattern.groupindex
{'name': 1, 'number': 2}

这使用 RegexObject.groupindex 属性

(?P<id>) 定义的任何符号组名称映射到组号的字典。如果模式中没有使用符号组,则字典为空。

如果您只能访问匹配对象,则可以使用 MatchObject.re 属性 获取模式:

 >>> a = list(re.finditer(r'(?P<name>\w+)|(?P<number>\d+)', 'Ala ma kota'))
>>> a[0]
<_sre.SRE_Match object at 0x100264ad0>
>>> a[0].re.groupindex
{'name': 1, 'number': 2}

如果您想知道哪个组匹配,请查看值; None 表示一个组从未在比赛中使用过:

 >>> a[0].groupdict()
{'name': 'Ala', 'number': None}

number 组从未用于匹配任何内容,因为它的值为 None

然后,您可以使用以下命令找到正则表达式中使用的名称:

 names_used = [name for name, value in matchobj.groupdict().iteritems() if value is not None]

或者如果只有 一个 组可以匹配,您可以使用 MatchObject.lastgroup

 name_used = matchobj.lastgroup

作为旁注,您的正则表达式有一个致命的缺陷; \d 匹配的所有内容也与 \w 匹配。你永远不会看到 number 用于 name 可以首先匹配的地方。反转模式以避免这种情况:

 >>> for match in re.finditer(r'(?P<name>\w+)|(?P<number>\d+)', 'word 42'):
...     print match.lastgroup
...
name
name
>>> for match in re.finditer(r'(?P<number>\d+)|(?P<name>\w+)', 'word 42'):
...     print match.lastgroup
...
name
number

但要考虑到以数字开头的单词仍然会使您的简单情况混淆:

 >>> for match in re.finditer(r'(?P<number>\d+)|(?P<name>\w+)', 'word42 42word'):
...     print match.lastgroup, repr(match.group(0))
...
name 'word42'
number '42'
name 'word'

原文由 Martijn Pieters 发布,翻译遵循 CC BY-SA 3.0 许可协议

首先,您的正则表达式在语法上是错误的:您应该将其写为 r'(?P<name>\w+)|(?P<number>\d+)' 。此外,即使这个 reg expr 也不起作用,因为特殊序列 \w 匹配所有字母数字字符,因此也匹配 \d 匹配的所有字符。您应该将其更改为 r'(?P<number>\d+)|(?P<name>\w+)' 以赋予 \d 优先于 \w 。但是,您可以使用匹配对象的属性 lastgroup 获取匹配组的名称,即: [m.lastgroup for m in re.finditer(r'(?P<number>\d+)|(?P<name>\w+)', 'Ala ma 123 kota')] 生成: ['name', 'name', 'number', 'name']

原文由 davidedb 发布,翻译遵循 CC BY-SA 3.0 许可协议

推荐问题