코딩공부/점프 투 파이썬

## 점프 투 파이썬 - 정규 표현식 시작하기 ( 3 )

integerJI 2020. 5. 19. 21:18

## 점프 투 파이썬 - 정규 표현식 시작하기

 

출처 : https://wikidocs.net/4308

 

# match 객체의 메서드

 

method 목적

group()  매치된 문자열을 돌려준다.

start()    매치된 문자열의 시작 위치를 돌려준다.

end()     매치된 문자열의 끝 위치를 돌려준다.

span()    매치된 문자열의 (시작, )에 해당하는 튜플을 돌려준다.

 

ex) m = p.match("python")

m.group() >>> 'python'

m.start() >>> 0

m.end() >>> 6

m.span() >>> (0, 6)

 

match 객체의 start()의 결괏값은 항상 문자열의 시작부터 조사하기 때문에 0이다.

 

# search 메서드 사용

ex) m = p.search("3 python")

m.group() >>> 'python'

m.start() >>> 2

m.end() >>> 8

m.span() >>> (2, 8)

 

# 모듈 단위로 수행하기

p = re.compile('[a-z]+')

+

m = p.match("python")

=

m = re.match('[a-z]+', "python")

컴파일과 match 메서드를 한 번에 수행할 수 있다.

 

한 번 만든 패턴 객체를 여러 번 사용해야 할 때는 re.compile을 사용

 

# 컴파일 옵션

DOTALL(S) - . 줄바꿈 문자를 포함하여 모든 문자와 매치

IGNORECASE(I) - 대소문자에 관계없이 매치

MULTILINE(M) - 여러줄과 매치할 수 있다. (^, $ 메타문자의 사용과 관계가 있는 옵션)

VERBOSE(X) - verbose 모드를 사용할 수 있다. (정규식을 보기 편하게 만들 수 있고 주석등을 사용)

 

옵션을 사용할 때는 re.DOTALL처럼 전체 옵션 이름을 써도 되고 re.S처럼 약어를 써도 된다.

 

# DOTALL, S

. 메타 문자는 줄바꿈 문자(\n)를 제외한 모든 문자와 매치되는 규칙이 존재

만약 \n 문자도 포함하여 매치하고 싶다면 re.DOTALL 또는 re.S 옵션을 사용해 정규식을 컴파일하면 된다.

 

import re

p = re.compile('a.b')

m = p.match('a\nb')

print(m) >>> None

 

정규식이 a.b인 경우 문자열 a\nb는 매치되지 않는다.

\n은 . 메타 문자와 매치되지 않기 때문이며 \n 문자와도 매치되게 하려면 다음과 같이 re.DOTALL 옵션을 사용해야 한다.

 

p = re.compile('a.b', re.DOTALL)

m = p.match('a\nb')

print(m) >>> <_sre.SRE_Match object at 0x01FCF3D8>

 

보통 re.DOTALL 옵션은 여러 줄로 이루어진 문자열에서 \n에 상관없이 검색할 때 많이 사용한다.

 

# IGNORECASE, I

re.IGNORECASE 또는 re.I 옵션은 대소문자 구별 없이 매치를 수행할 때 사용하는 옵션

 

p = re.compile('[a-z]', re.I)

p.match('python') >>> <_sre.SRE_Match object at 0x01FCFA30>

 

p.match('Python') >>> <_sre.SRE_Match object at 0x01FCFA68>

 

p.match('PYTHON') >>> <_sre.SRE_Match object at 0x01FCF9F8>

 

[a-z] 정규식은 소문자만을 의미하지만 re.I 옵션으로 대소문자 구별 없이 매치된다.

 

# MULTILINE, M

re.MULTILINE 또는 re.M 옵션은 메타 문자인 ^, $와 연관된 옵션이며 ^는 문자열의 처음을 의미하고, $는 문자열의 마지막을 의미한다.

정규식이 ^python인 경우 문자열의 처음은 항상 python으로 시작해야 매치되고, 정규식이 python$이라면 문자열의 마지막은 항상 python으로 끝나야 매치된다는 뜻이다.

 

import re

p = re.compile("^python\s\w+")

 

data = """python one

life is too short

python two

you need python

python three"""

 

print(p.findall(data))

 

정규식 ^python\s\w+ python이라는 문자열로 시작하고 그 뒤에 whitespace, 그 뒤에 단어가 와야 한다는 의미이다. 검색할 문자열 data는 여러 줄로 이루어져 있다.

 

>>> ['python one']

 

^ 메타 문자에 의해 python이라는 문자열을 사용한 첫 번째 줄만 매치된 것이다.

 

 

하지만 ^ 메타 문자를 문자열 전체의 처음이 아니라 각 라인의 처음으로 인식시키고 싶은 경우 re.MULTILINE 또는 re.M를 사용

 

import re

p = re.compile("^python\s\w+", re.MULTILINE)

 

data = """python one

life is too short

python two

you need python

python three"""

 

print(p.findall(data))

 

re.MULTILINE 옵션으로 인해 ^ 메타 문자가 문자열 전체가 아닌 각 줄의 처음이라는 의미를 갖게 되었다.

 

>>> ['python one', 'python two', 'python three']

 

re.MULTILINE 옵션은 ^, $ 메타 문자를 문자열의 각 줄마다 적용해 주는 것이다.

 

# VERBOSE, X

 

re.VERBOSE 또는 re.X 옵션을 사용해 정규식을 주석 또는 줄 단위로 구분할 수 있다

 

charref = re.compile(r'&[#](0[0-7]+|[0-9]+|x[0-9a-fA-F]+);')

 

=

 

charref = re.compile(r"""

 &[#]                # Start of a numeric entity reference

 (

     0[0-7]+         # Octal form

   | [0-9]+          # Decimal form

   | x[0-9a-fA-F]+   # Hexadecimal form

 )

 ;                   # Trailing semicolon

""", re.VERBOSE)

 

첫 번째와 두 번째 예를 비교해 보면 컴파일된 패턴 객체인 charref는 모두 동일한 역할을 한다.

하지만 정규식이 복잡할 경우 두 번째처럼 주석을 적고 여러 줄로 표현하는 것이 훨씬 가독성이 좋다는 것을 알 수 있다.

 

re.VERBOSE 옵션을 사용하면 문자열에 사용된 whitespace는 컴파일할 때 제거된다( [ ] 안에 사용한 whitespace는 제외). 그리고 줄 단위로 #기호를 사용하여 주석문을 작성할 수 있다.

 

# 백슬래시 문제

 

ex) \section >>> [ \t\n\r\f\v]ection

 

이 정규식은 \s 문자가 whitespace로 해석되어 의도한 대로 매치가 이루어지지 않는다.

 

올바르게 사용하려면

 

\\section

 

위처럼 정규식을 만들어서 컴파일하면 실제 파이썬 정규식 엔진에는 파이썬 문자열 리터럴 규칙에 따라 \\ \로 변경되어 \section이 전달된다. ( 파이썬에서만 해당하는 문제이다. )

 

결국 정규식 엔진에 \\ 문자를 전달하려면 파이썬은 \\\\처럼 백 슬래시를개나 사용해야 한다.

 

p = re.compile('\\\\section')

 

\를 계속 반복되는 정규식이라면 너무 복잡하다.

 

그래서 생긴 게 컴파일해야 하는 정규식이 Raw String임을 알려주는 파이썬 문법이다.

 

p = re.compile(r'\\section')

 

위와 같이 정규식 문자열 앞에 r 문자를 삽입하면 이 정규식은 Raw String 규칙에 의하여 백 슬래시개 대신 1개만 써도 2개를 쓴 것과 동일한 의미를 갖게 된다.

 

※ 만약 백 슬래시를 사용하지 않는 정규식이라면 r의 유무에 상관없이 동일한 정규식이 될 것이다.