[정규식] Greedy 와 Non-Greedy 매칭 Develop Tip

정규식은 매번 새롭게 다가올 때마다 새롭습니다.
마치 VI 에 대해서 아무 불편 없이 사용하고 있다가도
최신의 무언가를 하려고 하면 꼭 기능이 있듯이 말이지요.

암튼 처음 정규식을 배우는 분들도 알만한 내용을 이제사 알게되어
내심 부끄러운 마음으로 동일한 시행착으를 겪지 마시라고 이 글을 올립니다.

간단한 예를 들어,

"<title>This is a title.</title>..."
이라는 문자열이 있고, 여기에서
<(.*)> 라고 검색을 합니다.

그러면 "<title>" 이 검색될까요, 아니면 "<title>This is a title.</title>"
이 검색될까요?

정답은 "<title>This is a title.</title>" 입니다.

그 이유는 중간에 매칭되는 마구 마구 욕심스럽게 (greedy) 매칭을 하여
최대로 매칭되지 않을때 까지 매칭시키기 때문입니다.

따라서 정규식은 디폴트로 Greedy 방식의 매칭을 합니다.

이것을 해결하는 간단한 방법은, Non-Greedy 로 변환하는 것인데,

.* 매칭 대신 .*? 이라고 주는 것입니다.
또는 .+ ==> .+?


또 다른 예를 들어 봅니다.

'{item1={a=true, b=true}, item2={c="aa", d="dd"},},'
라는 문자열이 있습니다. (파이썬 형식이라 생각하십시오)

여기에서 item1={(...)}, ... 와 같이 item1의 중괄호 안에 있는 'a=true, b=true'
를 구해 오려고 합니다.

간단한 파이썬 프로그램을 작성했습니다.

import re
_re_monthly = re.compile(r'item1=\{(.+)\},')
m = _re_monthly.search(line)
str_monthly = m.group(1)
print str_monthly

이것을 수행했지만,
a=true, b=true}, item2={c="aa", d="dd"},
라는 결과가 나옵니다.

그 원인이 Greedy 임을 알았습니다.

결론적으로 위의 프로그램에서

import re
_re_monthly = re.compile(r'item1=\{(.+?)\},')
m = _re_monthly.search(line)
str_monthly = m.group(1)
print str_monthly

라고 하면, 원하는 
a=true, b=true
결과를 얻을 수 있었습니다.


저처럼 무식해서 고생하신 분이 혹시라도 계시다면,
어느 분께는 도움이 되셨기를 바랍니다.



덧글

  • ㅁㄴㅇㄹ 2020/01/06 09:40 # 삭제 답글

    많은 도움이 되었습니다 감사합니다!!!
  • 지훈현서아빠 2020/01/18 16:02 #

    도움이 되셨다니 저의 보람입니다~ ^^
댓글 입력 영역

구글애드텍스트