2012-09-28 2 views
0

다음과 같은 문자열이 표시됩니다. \input{{whatever}{1}}\mypath{{path1}{path2}{path3}...{pathn}}\shape{{0.2}{0.3}} path1, path2, ... pathn과 같은 모든 경로를 캡처하고 싶습니다. 파이썬에서 re 모듈을 사용해 보았습니다. 그러나 다중 캡처는 지원하지 않습니다. 예 : r"\\mypath\{(\{[^\{\}\[\]]*\})*\}"은 마지막으로 일치하는 그룹 만 반환합니다. 내가 생각 왜이 시점에서정규식으로 여러 반복 패턴을 캡처하는 방법은 무엇입니까?

>>> gpathRegexPat=r"\\mypath\{(\{[^{}[\]]*\})*\}" 
    >>> gpathRegexCp=re.compile(gpathRegexPat, flags=re.I|re.U) 
    >>> strpath=gpathRegexCp.search(r'\input{{whatever]{1}}\mypath{{sadf}{ad}}\shape{{0.2}{0.1}}').group() 
    >>> strpath 
    '\\mypath{{sadf}{ad}}' 
    >>> p.findall(strpath) 
    ['sadf', 'ad'] 

:

gpathRegexPat=r"(?:\\mypath\{)((\{[^\{\}\[\]]*\})*)(?:\})" 
    gpathRegexCp=re.compile(gpathRegexPat) 
    strpath=gpathRegexCp.search(r'\mypath{{sadf}{ad}}').groups()[0] 
    >>> strpath 
    '{sadf}{ad}' 
    p=re.compile('\{([^\{\}\[\]]*)\}') 
    >>> p.findall(strpath) 
    ['sadf', 'ad'] 

또는 : 나는이 작업을 수행하는 다른 방법을 발견 groups() 다음

("{path2}",)search(r"\mypath{{path1}{path2}})"에 패턴 만 돌아갑니다 적용 원래 문자열에서 findall을 사용 하시겠습니까? 나는 다음을 사용할 수있다 : gpathRegexPat=r"(?:\\mypath\{)(?:\{[^\{\}\[\]]*\})*?\{([^\{\}\[\]]*)\}(?:\{[^\{\}\[\]]*\})*?(?:\})" : 첫 번째 (?:\{[^\{\}\[\]]*\})*?이 0 시간과 일치하고 두 번째 (?:\{[^\{\}\[\]]*\})*?이 1 시간과 일치하면 sadf을 캡처한다. 첫 번째 (?:\{[^\{\}\[\]]*\})*?이 1 번과 일치하면 두 번째 것이 0 번과 일치하면 ad을 캡처합니다. 그러나이 정규식은 ['sadf'] 만 반환합니다.

으로 모든 여분의 패턴 ((?:\\mypath\{)(?:\})), 실제로 작동 아웃 :

>>> p2=re.compile(r'(?:\{[^\{\}\[\]]*\})*?\{([^\{\}\[\]]*)\}(?:\{[^\{\}\[\]]*\})*?') 
    >>> p2.findall(strpath) 
    ['sadf', 'ad'] 
    >>> p2.findall('{adadd}{dfada}{adafadf}') 
    ['adadd', 'dfada', 'adafadf'] 

누군가가 나에게이 동작을 설명 할 수 있습니까? 원하는 결과를 얻을 수있는 더 똑똑한 방법이 있습니까?

답변

1

당신 말이 맞습니다. 그룹 내에서 반복되는 하위 그룹을 반환 할 수는 없습니다. 원하는 것을하기 위해 정규식을 사용하여 그룹을 캡처 한 다음 두 번째 정규 표현식을 사용하여 반복 된 하위 그룹을 캡처 할 수 있습니다.

이 경우 해당 내용은 \\mypath{(?:\{.*?\})}입니다. 반환 할 {path1}{path2}{path3}

그런 다음 해당 문자열 안에 {pathn}의 반복 패턴을 찾으려면 \{(.*?)\}을 사용하면됩니다. 이것은 중괄호와 일치합니다. .*?은 욕심이없는 버전 인 .*입니다. 가능한 가장 긴 매치 대신 가장 짧은 가능한 매치를 반환합니다.

+0

N ote : [regex] (http://pypi.python.org/pypi/regex/0.1.20120904) 모듈은 반복 캡처를 지원합니다. 이 경우에는 필요하지 않지만 – jfs

+0

@ 세바스챤. 감사! 내가 생각한 빌드 인 모듈이 아닙니다. – Wang

+0

@ 한자. 감사! 정규 표현식 'r'(? : \\ mypath \ {) (? : \ {[^ \ {\} \ [\] * \}) *? \ { "?"는'findall()로 모든 경로를 반환 할 수 없습니다. {\} \ {\} \ *()()'중 하나입니까? – Wang

1
re.findall("{([^{}]+)}",text) 

반환

['path1', 'path2', 'path3', 'pathn'] 
마지막

my_path = r"\input{{whatever}{1}}\mypath{{path1}{path2}{path3}...{pathn}}\shape{{0.2}{0.3}}" 
#get the \mypath part 
my_path2 = [p for p in my_path.split("\\") if p.startswith("mypath")][0] 
print re.findall("{([^{}]+)}",my_path2) 

또는 더 나은 작동합니다

re.findall("{(path\d+)}",text) #will only return things like path<num> inside {} 
+0

Wang의 경로 지정을 존중하려면 정규식은'r "\ {([^ {} [\]] *) \}"'이어야합니다. – Matthias

+1

@ 조란, 답장을 보내 주셔서 감사합니다.하지만 다른 문자 안에 묻혀있는 문자열을 고려하십시오. \ input {{whatever} {1}} \ mypath {{path1} {path2} {path3} ... {pathn}} \ shape { {0.1} {0.2}}'. 그것은'input {}'과'\ shape {}'에서 매개 변수를 잡을 것입니다. 2 단계 캡처를 사용해야합니다. – Wang

+0

나중에 편집 된 답변 ... –

관련 문제