2016-09-09 3 views
2

파이썬에서, 비 캡처 그룹 내에서 어떻게 그룹을 캡처합니까? 다른 방법으로, 캡처 링 그룹을 포함하는 캡처되지 않는 하위 패턴을 어떻게 반복합니까?비 캡처 그룹 내의 Regex 캡쳐 그룹

예를 들어 가져 오기 문자열의 모든 패키지 이름을 캡처 할 수 있습니다. 예 : 문자열 :

수입 팬더, 운영 체제, SYS

은 '팬더', 'OS'및 'SYS'를 반환합니다. 다음 패턴은 첫 번째 패키지를 캡처하고 두 번째 패키지에 일어나서 :

import\s+([a-zA-Z0=9]*),*\s* 

여기에서 내가 즉 ([a-zA-Z0=9]*),*\s*을, 그룹을 캡처하고 다음 문자와 일치하는 하위 패턴을 반복하고 싶습니다. 이 하위 패턴을 비 캡처 그룹으로 묶고 반복 할 때 :

import\s+(?:([a-zA-Z0=9]*),*\s*)* 

더 이상 그룹을 캡처하지 않습니다.

+0

을 PyPi 정규식 모듈. –

+0

문제는 그룹 및 비 캡처 그룹을 캡처하는 데 문제가되지 않습니다. 문제는 나중에 사용할 수 있도록 _unset_ 개의 변수를 얻으려는 것입니다. 캡처 그룹에 대해 '*'를 사용하면 원하는 결과가 거의 산출되지 않습니다. 이것은 일반적으로 사용되는 정규식이 아닙니다. 대신 합리적인 것은 전체 가져 오기 패키지 세트를 가져 와서 문자열을', \ s * (? = \ w)'또는 그와 비슷한 것으로 분리하는 것입니다. –

답변

1

귀하의 질문은 정규식에 대해 엄격하게 표현되어 있지만 recursive descent parser (예 : pyparsing)을 사용하려는 경우 전문 지식을 필요로하는 많은 것들이 매우 간단 해집니다.

예, 여기에 무엇을 요구하는지 것은

Suppress(Literal('import')) + commaSeparatedList 

또한 정규식보다 더 직관적,

from pyparsing import * 

p = Suppress(Literal('import')) + commaSeparatedList 

>>> p.parseString('import pandas, os, sys').asList() 
['pandas', 'os', 'sys'] 

>>> p.parseString('import     pandas,    os').asList() 
['pandas', 'os'] 

그것은 개인 취향의 문제 일 수 있지만, 나에 수도가된다 .

0

반복 캡처 그룹은 만 마지막 반복을 캡처합니다. 이것이 re.findall으로 작업 할 정규 표현식을 재구성해야하는 이유입니다.

\s* 
(?: 
    (?:^from\s+ 
    ( # Base (from (base) import ...) 
     (?:[a-zA-Z_][a-zA-Z_0-9]* # Variable name 
     (?:\.[a-zA-Z_][a-zA-Z_0-9]*)* # Attribute (.attr) 
    ) 
    )\s+import\s+ 
) 
| 
    (?:^import\s|,)\s* 
) 
( # Name of imported module (import (this)) 
    (?:[a-zA-Z_][a-zA-Z_0-9]* # Variable name 
    (?:\.[a-zA-Z_][a-zA-Z_0-9]*)* # Attribute (.attr) 
) 
) 
(?: 
    \s+as\s+ 
    ( # Variable module is imported into (import foo as bar) 
    (?:[a-zA-Z_][a-zA-Z_0-9]* # Variable name 
     (?:\.[a-zA-Z_][a-zA-Z_0-9]*)* # Attribute (.attr) 
    ) 
) 
)? 
\s* 
(?=,|$) # Ensure there is another thing being imported or it is the end of string 

Try it on regex101.com

캡처 그룹 0은 Base 될 것 캡처 그룹 1은 가져온 모듈의 이름 및 캡처 그룹 2 모듈 인 변수가 될 것이다 (필요하시면)입니다 (from (group 0) import (group 1) as (group 2))

import re 

regex = r"\s*(?:(?:^from\s+((?:[a-zA-Z_][a-zA-Z_0-9]*(?:\.[a-zA-Z_][a-zA-Z_0-9]*)*))\s+import\s+)|(?:^import\s|,)\s*)((?:[a-zA-Z_][a-zA-Z_0-9]*(?:\.[a-zA-Z_][a-zA-Z_0-9]*)*))(?:\s+as\s+((?:[a-zA-Z_][a-zA-Z_0-9]*(?:\.[a-zA-Z_][a-zA-Z_0-9]*)*)))?\s*(?=,|$)" 

print(re.findall(regex, "import pandas, os, sys")) 
[('', 'pandas', ''), ('', 'os', ''), ('', 'sys', '')] 

에 당신은 다른 두 개의 C를 제거 할 수 있습니다 당신이 그들을 돌보지 않는다면 그룹을 확보 할 수 있습니다.

0

당신은 당신의 import\s+(?:([a-zA-Z0-9=]+),*\s*)* 정규식 (난 그냥 어떤 숫자를 일치하도록 0-9 범위를 고정 끝까지 =를 포함)을 사용 PyPi regex module를 사용하여 그룹 1 캡처 스택에 액세스 할 수 있습니다 : 당신이 기능을 사용하려면

>>> import regex 
>>> s = 'import pandas, os, sys' 
>>> rx = regex.compile(r'^import\s+(?:([a-zA-Z0-9=]+),*\s*)*$') 
>>> print([x.captures(1) for x in rx.finditer(s)]) 
[['pandas', 'os', 'sys']]