저는 점프투파이썬 교재로 공부합니다. 이 교재를 바탕으로 공부한 걸 정리합니다.
1️⃣ 정규표현식이란? 문자 클래스, Dot(.), 반복(*), 반복(+), 반복({m,n}, ?)
2️⃣ 정규 표현식(2) - 문자열 검색(match, search, findall, finditer)
3️⃣ 정규표현식(3) - match 객체의 메서드(group, start, end, span)
4️⃣ 정규표현식(4) - COMPILE 옵션 - (DOTALL, IGNORECASE, MULTILINE, VERBOSE)
5️⃣ 정규 표현식(5) - 백슬래시 문제('\n')
6️⃣ 정규 표현식(6) 메타 문자 - |, ^, $, \A, \Z, \b, \B
7️⃣ 정규표현식(7) 그루핑, 전방 탐색, 문자열 바꾸기, Greedy vs Non-Greedy
앞에서 살펴 보았던 메타 문자 +, *, [], {} 등의 메타 문자는 매치가 진행될 때 현재 매치되고 있는 문자열이 소비됩니다.
문자열 소비가 없는 메타 문자도 있습니다.
문자열 소비가 없는 메타 문자를 zero-width assertions이라 한다.
| 메타 문자는 or과 동일한 의미로 사용됩니다. A|B라는 정규식이 있다면 A 또는 B라는 의미입니다.
import re
p = re.compile('Crow|Servo')
m = p.match('CrowHello')
print(m)
<re.Match object; span=(0, 4), match='Crow'>
^ 메타 문자는 문자열의 맨 처음과 일치함을 의미합니다.
앞에서 살펴본 컴파일 옵션 re.MULTILINE을 사용할 경우에는 여러 줄의 문자열일 때, 각 줄의 처음과 일치하게 됩니다.
print(re.search('^Life', 'Life is too short'))
print(re.search('^Life', 'My Life'))
<re.Match object; span=(0, 4), match='Life'>
None
'^Life' 정규식이 Life 문자열이 처음에 온 경우에는매치하지만 처음 위치가 아닌 경우에는 매치하지 않음을 알 수 있습니다.
$ 메타 문자는 ^ 메타 문자와 반대의 경우입니다. 즉, $는 문자열의 끝과 매치되지만, 그 외의 경우에는 매치되지 않습니다.
import re
print(re.search('short$', 'Life is too short'))
print(re.search('short$', 'My Life is too short, you need python'))
<re.Match object; span=(12, 17), match='short'>
None
여기서도 'short$'의 정규식을 통해 문자열의 끝 부분에 short가 오면 매치, 아니면 매치가 되지 않음을 알 수 있습니다.
\^, \$ 로 사용하면 됩니다.
import re
print(re.search('short\$', 'Life is too short$'))
print(re.search('short\$', 'My Life is too short$, you need python'))
해당 코드의 결과가 어떻게 나왔을까요? 이 부분은 책에 없는 코드입니다. 그냥 어떻게 나오나 참고하기 위해 작성한 코드입니다.
<re.Match object; span=(12, 18), match='short$'>
<re.Match object; span=(15, 21), match='short$'>
둘 다 매치됩니다. 저도 처음에 결괏값을 보고 헷갈렸는데, search는 문자열 전체에서 검색해주는 아이였고, 두 문자열 모두 short$를 포함하기 때문에 매치된다고 볼 수 있습니다.
\A는 문자열의 처음과 매치됨을 의미합니다. ^ 메타 문자와 동일한 의미이지만 re.MULTILINE 옵션을 사용할 경우 다르게 해석됩니다.
re.MULTILINE 옵션을 사용할 경우, ^은 각 줄의 문자열의 처음과 매치되지만 \A는 줄과 상관없이 전체 문자열의 처음하고만 매치됩니다.
import re
p = re.compile("\\Apython\s\w+", re.MULTILINE)
data = """python one
life is too short
python two
you need python
python three"""
print(p.findall(data))
해당 "\Apython\s\w+" 정규 표현식과 re.MULTILINE 옵션이 쓰였지만
결괏값은
['python one']
만 나옴을 통해 \A는 줄과 상관없이 전체 문자열의 처음하고만 매치된다는 것을 알 수 있습니다.
\Z는 문자열의 끝과 매치됩니다. 이것 역시 \A와 동일하게 re.MULTILINE 옵션을 사용할 경우, $ 메타 문자와는 다르게 전체 문자열의 끝과만 매치됩니다.
\b는 단어 구분자(Word Boundary)입니다. 보통 단어는 whitespace에 의해 구분됩니다.
import re
p = re.compile(r'\bclass\b')
print(p.search('no class at all'))
<re.Match object; span=(3, 8), match='class'>
'\bclass\b' 정규식은 앞뒤가 whitespace로 구분된 class라는 단어와 매치됨을 의미합니다. 따라서 no class at all의 class라는 단어와 매치됨을 알 수 있습니다.
import re
p = re.compile(r'\bclass\b')
print(p.search('the declassified algorithm'))
print(p.search('one subclass is'))
None
None
두 문장 모두 문자열 안에 class가 들어가 있지만 whitespace로 구분된다는 '\bclass\b'
정규식과 매치되지 않기에 둘 다 None이 나옵니다.
❗ \b 메타 문자 사용시 주의점이 있습니다다.
\b는 파이썬 리터럴 규칙에 의하면 백스페이스를 의미하므로 백스페이스가 아닌 구분자임을 알려주기 위해서 r'\bclass\b'
처럼 Raw String임을 알려주는 기호 r을 반드시 사용해야 합니다!
\B 메타 문자는 \b 메타 문자와 반대의 경우입니다. 즉, whitespace로 구분된 단어가 아닌 경우에만 매치됩니다.
import re
p = re.compile(r'\Bclass\B')
print(p.search('no class at all'))
print(p.search('the declassified algorithm'))
print(p.search('one subclass is'))
None
<re.Match object; span=(6, 11), match='class'>
None
class 단어의 앞뒤에 whitespace가 하나라도 있는 경우에는 매치가 안 되는 것을 알 수 있습니다.
세 번째 subclass의 경우에도 오른쪽에 whitespace가 있기 때문에 매치되지 않았습니다.
이렇게 메타 문자의 정리를 마치겠습니다!