English 中文(简体)
找出Python正则表达式中捕获组的数量
原标题:
  • 时间:2008-09-24 13:14:50
  •  标签:

有没有办法确定给定的正则表达式中有多少个捕获组?

我希望能够做到以下几点:

def groups(regexp, s):
    """ Returns the first result of re.findall, or an empty default

    >>> groups(r (d)(d)(d) ,  123 )
    ( 1 ,  2 ,  3 )
    >>> groups(r (d)(d)(d) ,  abc )
    (  ,   ,   )
    """
    import re
    m = re.search(regexp, s)
    if m:
        return m.groups()
    return (  ,) * num_of_groups(regexp)

这让我可以做一些事情,比如:

first, last, phone = groups(r (w+) (w+) ([d-]+) ,  John Doe 555-3456 )

然而,我不知道如何实现num_of_groups。(目前我只是围绕它工作。)

编辑:按照rslite的建议,我用重新搜索替换了的重新查找

sre_parse似乎是最健壮、最全面的解决方案,但需要遍历树,而且似乎有点重。

MizardX的正则表达式似乎涵盖了所有的基,所以我将使用它。

最佳回答
def num_groups(regex):
    return re.compile(regex).groups
问题回答
f_x = re.search(...)
len_groups = len(f_x.groups())

sre_parse内部的一些东西可能会有所帮助。

乍一看,可能是这样的:

>>> import sre_parse
>>> sre_parse.parse( (d)d(d) )
[( subpattern , (1, [( in , [( category ,  category_digit )])])), 
( in , [( category ,  category_digit )]), 
( subpattern , (2, [( in , [( category ,  category_digit )])]))]

即计数子模式类型的项目:

import sre_parse

def count_patterns(regex):
    """
    >>> count_patterns( foo: d )
    0
    >>> count_patterns( foo: (d) )
    1
    >>> count_patterns( foo: (d(s)) )
    1
    """
    parsed = sre_parse.parse(regex)
    return len([token for token in parsed if token[0] ==  subpattern ])

注意,我们在这里只计算根级别的模式,所以最后一个例子只返回1。要改变这一点,令牌将需要递归搜索。

首先,如果你只需要re.findall的第一个结果,那么最好只使用返回匹配或无的re.search。

对于组号,您可以计算左括号的数量(转义符除外。您可以使用另一个正则表达式:

def num_of_groups(regexp):
    rg = re.compile(r (?<!\)( )
    return len(rg.findall(regexp))

请注意,如果正则表达式包含非捕获组,并且(通过将其用作[(]进行转义),则此操作不起作用。因此,这不是很可靠。但取决于您使用的正则表达式,它可能会有所帮助。

使用您的代码作为基础:

def groups(regexp, s):
    """ Returns the first result of re.findall, or an empty default

    >>> groups(r (d)(d)(d) ,  123 )
    ( 1 ,  2 ,  3 )
    >>> groups(r (d)(d)(d) ,  abc )
    (  ,   ,   )
    """
    import re
    m = re.search(regexp, s)
    if m:
        return m.groups()
    return (  ,) * len(m.groups())

这可能是错误的,但我认为没有办法找到正则表达式匹配时返回的组数。我能想到的使其按您希望的方式工作的唯一方法是将特定regex期望的匹配数作为参数进行传递。

不过要澄清的是:当findall成功时,您只希望返回第一个匹配项,但当它失败时,您想要一个空字符串列表?因为注释似乎显示所有匹配项都以列表的形式返回。





相关问题
热门标签