2022년 10월 19일 수요일

파이썬 정규식, Greedy Non Greedy탐색(최소일치/최대일치)

 이번엔 파이썬의 정규식(RegEx)중 Greedy match/Non-Greedy match부분을 설명합니다.

아래와 같은 예제에서 첫번째 괄호만 매치를 시키자고 하고합니다.

text = '(Machester 10) (London 20) (Seoul 30) (Tokyo 40)'

그렇지만, 실제로 아래와 같은 예제를 보면, 첫번째 괄호만 매치되는 게 아니라 마지막 괄호까지 전부 매치가 됩니다.

(.*) - Greedy match

(Manchester 10) (London  20) (Seoul 30) (Tokyo 40)

(.*?) - Non Greedy match (Manchester 10) (London  20) (Seoul 30) (Tokyo 40)

이것은 기본적으로 정규식은 Greedy match (최대한 많이 매치)를 하기 때문인데, 이렇게 되면 원래 의도와는 다른 결과가 나올 수 있습니다.

그래서 .* 뒤에 ?를 붙여서 .*? 과 같이 표현합니다. 그러면, 이 탐색자가 가장 많이 매치되는 경우를 찾아주는 것이 아니라 가장 적게 매치되는 경우를 찾아줍니다.

text = '(Machester 10) (London 20) (Seoul 30) (Tokyo 40)'
p = re.compile(r'(\(.*\))')
if m:= p.search(text): print (m.groups()) 
# ('(Machester 10) (London 20) (Seoul 30) (Tokyo 40)',)

p = re.compile(r'(\(.*?\))')
if m:= p.search(text): print (m.groups()) 
# ('(Machester 10)',)

이런 예는 종종 볼수 있습니다. 이것 말고도 HTML, XML match시킬때도 마찬가지 입니다. 또, C-style 주석도 이런 경우 종종 볼수 있습니다. /* ...  */ 와 같이 주석처리를 지우려고 하는데 , 텍스트 파일 전체가 지워지는 경우, 이 그리디매치가 적용이 되어서 그런것입니다.

가장 가까운 괄호와 매치시키고 싶은데, 반복자가 최대한 많이 매치시키려 하기 때문에, 이런 부분의 차이를 알고 있다면 정규식 쓰는데 좀더 활용도를 높일 수가 있습니다.

댓글 없음:

댓글 쓰기