找出Python正则表达式中捕获组的数量

找出Python正则表达式中捕获组的数量,python,regex,Python,Regex,有没有办法确定给定正则表达式中有多少捕获组 我希望能够做到以下几点: 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') (''

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

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

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')
但是,我不知道如何实现组的数量。(目前我正在努力解决这个问题。)

编辑:之后,我将
re.findall
替换为
re.search

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


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

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

对于组数,可以计算开括号“(”的数目,但以“\”转义的除外。可以使用另一个正则表达式:

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

rg=re.compile(r’(?来自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。要更改此值,需要递归搜索令牌。

可能是错误的,但我认为没有办法找到如果正则表达式匹配将返回的组数。我能想到的唯一方法是按照您的方式执行此操作希望它将特定正则表达式期望的匹配数作为参数传递


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

使用您的代码作为基础:

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())

当没有找到匹配项时,这将引发异常。这实际上不会返回组数,它将返回所有组的元组。为了返回组数,您需要以下代码(在Python 3.4中):
return len(re.compile(regex.groups())
@RaziShaban
re.compile(regex)).groups
是一个类型为
int
的属性。compile(regex).match(input).groups()
是一个方法,返回一个
元组
。对了,很抱歉,我使用的是findall,而不是compile。我要指出的是,您的函数名为
num\u groups
,但返回一个元组,而不是一个数字。我只喜欢使用len(match.groups())在完成match=re.search()或任何返回匹配对象的操作之后。谢谢,这是最好的一个。不需要编译任何东西,它已经完成了。如果搜索失败,这将不起作用。在这种情况下,f_x将为None,因此它不会有“groups”属性要检查。@nupanick因此需要检查
如果f_x:len(f_x.groups())
def num_groups(regex):
    return re.compile(regex).groups
f_x = re.search(...)
len_groups = len(f_x.groups())