【问题标题】:How to get group name of match regular expression in Python?如何在 Python 中获取匹配正则表达式的组名?
【发布时间】:2015-05-05 13:07:02
【问题描述】:

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

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

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

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

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

【问题讨论】:

    标签: python regex python-2.7


    【解决方案1】:

    你可以从编译后的表达式中得到这些信息

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

    这使用RegexObject.groupindex attribute:

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

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

    >>> 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 匹配。你永远不会看到 numbername 可以首先匹配的地方使用。反转模式以避免这种情况:

    >>> 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'
    

    【讨论】:

    • 不确定我是否可以使用 groupindex(它看起来显示了在 re 中定义的组而不是结果中的组)。我想知道我匹配了哪个组 &lt;integer&gt;&lt;name&gt; 或其他。
    • @Chameleon:任何设置为 None 的组都匹配。例如,a[0].group(2)Nonea[0].groupdict()['number'] 也是。
    • @Chameleon: 并考虑到您的模式可以包含的不仅仅是单个 OR (|) 组,match.group(0) 涵盖的文本比单个组更多。
    • Peters 我知道无论我在示例中犯了什么错误,re 是如何工作的 - re 确实是贪婪的,\w 不是 [^\W\d_]
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:
      name_pattern = "(((\s+)?)((?P<HeadCount>[0-9]{1,2})(?P<LastName>[A-Z]{1,})((([\/]{1,})?)((?P<FirstName>[A-Z]{1,})?)){0,}){1,})"
      
      name_text = "1GILL/HAROONCONSTANTSHER 1HAROON/ANILAMS"
      for match in re.finditer(name_pattern,name_text):
          print(match["LastName"])
      

      【讨论】:

        猜你喜欢
        • 2012-07-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-30
        • 2015-09-08
        • 2018-10-19
        • 2012-08-07
        相关资源
        最近更新 更多