2011년 2월 21일 월요일

[Python] Regular Expression API (정규표현식 API 기본)

정규표현식(Regular Expression)이란 문자열의 패턴을 이용해서 특정 문자열이 규칙에 맞는지, 혹은 특정 규칙에 따르는 문자열을 찾거나 뽑아내는 등, 이런 특정 텍스트 조합 패턴을 의미한다.

‘This is test string’ 이라는 문자열에서 ‘is’라는 문자열을 찾기는 쉽다. 하지만 ‘is’로 시작해서 중간에 뭔가 들어가고 끝에 ‘string’으로 끝나는 문자열을 검색해 내기란 쉽지 않다. 물론 구현은 가능하지만 코드량이 많아지고 귀찮다. 이를 단 몇 줄로 처리해 내는 것이 정규표현식의 능력이다.

정규표현식의 핵심은 패턴을 어떻게 만드냐이다.

http://docs.python.org/library/re.html

Python의 RE 패턴에 관한 내용의 정식 문서는 이 링크를 타고 가면 되겠지만, Regular Expression 자체는 Unix와 역사를 같이 한다 라는 궤변을 할 수 있을 정도로 역사도 오래되었고 형식도 다양하고 … 굳이 Python 말고도 찾아 볼 만한 가치는 있을 것 같다. (특히 Vim의 정규표현식을 알아두는 것도 좋다)

어쨌건 기본적인 뼈대를 보자.

import re

p = re.compile('RE-PATTERN')

if p.match('Some String'):
    pass

‘Some String’이라는 임의의 스트링에서 RE-PATTERN으로 정의한 패턴에 맞는지를 파악하는 루틴이다. 정규표현식은 어차피 패턴을 파악하는 데서 시작하니가 가장 기본적인 내용이다.

re.compile에서 볼 수 있는 부분에서 유추할 때 compile이란 과정은 문자열로 정의된 정규표현식을 특정 형식을 변환하는 거라 볼 수 있다. 이유야 아마도 성능상의 이유일 것이라고 유추된다. 어쨌건 한번 re.compile()을 해 둔 객체는 두고두고 써 먹을 수 있다는 의미.

앞서 이야기 했던 패턴 예를 하나 구현해 보자.

>>> p = re.compile('^.*is.+string$')
>>> p.match('aaa')
>>> p.match('there was no re string')
>>> p.match('this is test string')
<_sre.SRE_Match object at 0x0274EC28>

제대로 맞게 했는지는 모르겠지만 뭐 의도한 대로 되는 것 같다. 패턴 내용은 is와 string 사이에 하나 이상의 문자가 포함된 문자열인지 아닌지를 파악하는 것. 가장 마지막에 실행한 라인이 결과물이 리턴되었으니 원하는 것을 찾은 거라고 이해하자.

다음은 그룹에 관하여…

>>> p = re.compile('^.*is(.+)string$')
>>> s = p.match('this is test string')
>>> s.group(0)
'this is test string'
>>> s.group(1)
' test '

패턴에서 괄호로 묶어 놓은 것을 그룹이라고 보면 된다. 하나 이상의 문자가 이 그룹에 해당되고 0번은 무조건 매칭된 전체 스트링, 1번 부터는 차례대로 지정한 그룹에 해당된다.

패턴으로 매칭된 데이터의 변환도 물론 가능. 계속 이어서…

>>> p.sub(r'__\1__', 'this is test string')
'__ test __'

\1이라고 적은 부분에 유의. 그룹1번에 해당되는 단어를 넣는다면 표현으로 이해하면 된다. 어쨌든 결과적으로 매칭되는 패턴에서 1번 그룹 좌/우측에 밑줄(underscope)을 두 개씩 넣도록 해 봤다.

re모듈 자체에 엄청나게 많은 method가 있으니 소개한 기능은 세발의 피에 해당한다. 어쨌든 기본적인 부분만을 적는 거라 여기까지만. 나머지는 문서를 보자.

덤으로 E-Mail RE Pattern 한가지를 적고 도망:

[0-9a-z]([-_.\+]?[0-9a-z])*@[0-9a-z]([-_.]?[0-9a-z])*.[a-z]{2,3}

이 패턴을 이해한다면 기본적인 Python의 정규표현식을 무리없이 쓸 것 같다.

댓글 없음 :