P.238-239 정규표현식 질문있습니다.

108 views
Skip to first unread message

Jang Tae Jong

unread,
Jul 1, 2010, 5:00:56 AM7/1/10
to Python 3 질문 게시판
안녕하세요.

작년에 책 사고 이제야 시간이 나서 제대로 공부하고 있는 직장인입니다. ^^;

책 내용 중에 정규표현식 관련된 해석이 안되서 질문드립니다.

아래는 P.238 ~ 239에 걸쳐 나오는 <title> ... </title> tag 검출 정규표현식 패턴 내용인데요.

r".*?<title.*?>(.*)</title>"

여기서 궁금한 점은...
r".*?" 에서 '*' 문자랑 '?' 문자가 연속해서 나오면 의미가 어떻게 되는건가요?

'?' 의 경우 문자가 0회 또는 1회 반복.
'*' 의 경우 문자가 0회 이상 반복.

그래서 문자가 0회 이상 반복하는 패턴과는 차이가 있을까 해서
패턴중 '?'를 제거해 보았는데요.

r".*<title.*>(.*)</title>", 이렇게 변경하였는데 <title> tag 내용은 똑같이 검출이 되었습니다.

아래는 소스입니다. (부득이하게 2.6.5에서 테스트하였습니다.)

>>> web = urllib.urlopen("http://www.python.org")
>>> html = web.read()
>>> c = re.compile(r".*<title.*>(.*)</title>", re.I | re.S) # 이 부분을 패턴 r".*?<title.*?>(.*)</title>" 로 변경해도 결과는 같음.
>>> c.findall(html)
['Python Programming Language -- Official Website']

그래서 ... 결론적으로 ... 패턴에 '?' 추가되면 어떤 효과(?)가 있는지 궁금합니다.

그럼 답변 기다릴께요. 수고하세요~

Dsp

unread,
Jul 2, 2010, 10:49:36 PM7/2/10
to Python 3 질문 게시판
안녕하세요, 신호철입니다.
궁금해 하신 부분에 대해 답변 드리겠습니다 :)

정규식에 대해서 저희가 설명을 안 한 부분이 있는데,
정규식에는 greedy한 방식과 lazy(non-greedy)한 방식이 있습니다.

말씀하신, ".*"의 경우가 greedy한 방식입니다. 즉, 조건을 만족하는 한 가장 긴 문자열을 선택하려고 합니다.
그리고 반대의 경우, ".*?"의 경우가 lazy한 방식입니다. 조건을 만족하는 한 가장 짧은 문자열을 선택하려고 합니다.

음, 저도 써 놓고 보니 무슨 소리인지 모르겠네요 :)
질문에 사용하신 예제를 살짝 바꿔서 돌려보면 차이를 이해하실 수 있을 것입니다.

아래와 같이 "<"과 ">"로 둘러싼 문자열을 greedy하게 선택해 보겠습니다.

>>> import urllib
>>> html = urllib.urlopen('http://www.python.org').read()
>>> import re
>>> greedy = re.compile(r'<.*>', re.I|re.S)
>>> len( greedy.findall(html) )
1

엇, 결과 개수가 1개네요. 즉, <>로 둘러싼 가장 긴 문자열을 선택하려고 했으니 html 태그 전체를 선택하게 된 것을 보
실 수 있습니다.
이번에는 살짝 바꿔서 lazy하게 선택해 보겠습니다.

>>> lazy = re.compile(r'<.*?>', re.I|re.S)
>>> len ( lazy.findall(html) )
469

네, 이번에는 <>로 둘러싼 짧은 문자열을 선택했으니, 아마도 거의 모든 태그들을 선택한 것 같습니다 :)
이해하시는데 도움이 되었길 바랍니다.
감사합니다.

Ps.
현재 2쇄까지 출판되었는데,
다음 쇄에는 이러한 내용을 추가하는 것을 고려해 보도록 하겠습니다.

Reply all
Reply to author
Forward
0 new messages