2008-09-24 5 views
20

주어진 정규 표현식에 캡처 그룹이 몇 개 있는지 확인하는 방법이 있습니까?파이썬 정규 표현식에서 캡처 그룹 수 알아보기

나는 follwing을 할 수 있도록하고 싶습니다 :이 날처럼 물건을 수행 할 수 있습니다

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을 구현하는 방법을 모르겠어요. (현재 난 그냥 해결.)

편집 :advice from rslite에 따라, 나는 re.searchre.findall을 교체했다.

sre_parse은 가장 견고하고 포괄적 인 솔루션처럼 보이지만 트리를 통과해야하며 약간 무거워 보입니다.

MizardX의 정규 표현식이 모든 기반을 덮는 것처럼 보이므로 그걸로 갈 것입니다.

답변

29
def num_groups(regex): 
    return re.compile(regex).groups 
+5

실제로 그룹 수를 반환하지는 않으며 모든 그룹의 튜플을 반환합니다. 그룹 수를 반환하려면 파이썬 3.4에서 다음 코드가 필요합니다 :'return len (re.compile (regex) .groups())' –

+2

@RaziShaban're.compile (regex) .groups '는'int' 타입의 속성입니다. 're.compile (regex) .match (input) .groups()'메소드는'tuple'을 리턴합니다. –

+0

오른쪽, 죄송합니다, 나는 findall로 일하고 있었고, 컴파일하지 않았습니다. 내가 작성한 포인트는 함수의 이름이'num_groups'이지만 숫자가 아닌 튜플을 반환한다는 것입니다. –

1

우선 re.findall의 첫 번째 결과 만 필요하면 일치 또는 없음을 반환하는 re.search를 사용하는 것이 더 좋습니다. .이하지 않는 것을

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

참고 : 그룹의 경우

은 '(' '\'로 이스케이프 된 것을 제외하고 당신은 그 또 다른 정규식을 사용할 수 여는 괄호의 수를 셀 수 번호를 정규식에 비 캡처 그룹이 포함되어 있고 '('를 '[]]로 사용하여 이스케이프 처리하는 경우에도 작동합니다. 따라서 신뢰할 수는 없지만 사용하는 정규식에 따라 도움이 될 수도 있습니다.

2

일치 개체의 lastindex 속성은 찾고자하는 것이어야합니다. re module docs

를 참조하십시오.
+0

, 나는 일치하는 오브젝트가 없습니다. 게다가 lastindex는 그렇게 생각하지 않습니다. – itsadok

2

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을 반환하므로, 토큰 반복적으로 검색해야합니다.

0

잘못된 것 일지 모르지만 정규식이 일치하는 경우 반환 된 그룹 수를 찾는 방법은 없다고 생각합니다. 당신이 원하는 방식으로이 작업을 수행 할 수있는 유일한 방법은 특정 정규 표현식이 인수로 기대하는 일치 수를 전달하는 것입니다.

그래도 알 수 있습니다 : findall이 성공하면 첫 번째 일치 항목 만 반환하지만 실패하면 빈 문자열 목록을 원하십니까? 코멘트는 모든 일치가 목록으로 반환되는 것을 보여주기 때문입니다.

0

기초로 코드를 사용하여 :

일치하는 항목이없는 경우
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()) 
+0

일치하지 않는 경우 예외가 throw됩니다. – itsadok

0
f_x = re.search(...) 
len_groups = len(f_x.groups()) 
관련 문제