저는 점프투파이썬 교재로 공부합니다. 이 교재를 바탕으로 공부한 걸 정리합니다.
드디어 마지막 챕터까지 와서 기뻐했건만, 정규표현식을 만나고 보스를 만난 기분입니다.
(제가 깨본 보스맵은 방구대장 뿡뿡이 CD게임과 보글보글 시리즈 뿐...)
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
정규 표현식(Regular Expressions)은 복잡한 문자열을 처리할 때 사용하는 기법입니다. 파이썬만의 고유 문법이 아닌 문자열을 처리하는 모든 곳에서 사용됩니다.
자. 아래와 같은 문제가 있다고 해봅시다.
task: 주민등록번호를 포함하고 있는 텍스트가 있다. 이 텍스트에 포함된 모든 주민등록번호의 뒷자리를 * 문자로 변경해 보자.
data = """
park 800905-1049118
kim 700905-1059119
"""
# 결과를 담아줄 빈 리스트 생성
result = []
# 줄바꿈 되는 곳마다 split
for line in data.split('\n'):
word_result = []
# ' ' 공백마다 split
for word in line.split(' '):
# word의 길이가 14이면서, 앞 6자리와 뒤 7자리가 digit인 모든 조건을 만족하는
if len(word) == 14 and word[:6].isdigit() and word[7:].isdigit():
# word에 word에서 앞 6자리를 슬라이싱하여 '-'와 '*' 7개를 붙여준다.
word = word[:6] + '-' + '*******'
# for문 안에서 생성해둔 빈 리스트 word_result에 word 값을 담아준다.
word_result.append(word)
# result 에 word_result에 담긴 값을 ' ' 공백을 추가하여 담기
result.append(' '.join(word_result))
# 다시 그 결과를 '\n' 줄 바꿈하여 출력
print('\n'.join(result))
# 결론: 복잡하다.
park 800905-*******
kim 700905-*******
import re
data = """
park 800905-1049118
kim 700905-1059119
"""
pat = re.compile("(\d{6})[-]\d{7}")
print(pat.sub("\g<1>-*******", data))
park 800905-*******
kim 700905-*******
정규 표현식을 사용하면 이렇게 간단해집니다. 아직 정규 표현식을 배우지 않았으니 코드를 이해하긴 어렵겠지만 대충 살펴보니 "" 큰 따옴표 안에 괄호(), 대괄호{}, d는 digit을 처리해주는 기호 같고, g는 뭘까요? 아무튼 눈으로 대강 훑어봅니다.👀
# . ^ $ * + ? { } [ ] \ | ()
정규표현식에 사용되는 특별한 문자들입니다.
정규 표현식에 위의 메타 문자를 사용하면 특별한 의미를 갖게 됩니다. 하나씩 살펴보겠습니다.
[] 사이의 문자들과 매치 라는 의미를 갖습니다. [abc]라면 이 표현식의 의미는 'a, b, c 중 한 개의 문자와 매치'된다는 의미입니다.
정규식[abc] | 문자열 | 매치 여부 | 설명 |
---|---|---|---|
[abc] | a | 문자열 a와 매치⭕ | 'a'는 정규식과 일치하는 'a'가 있으므로 |
before | 문자열 before과 매치⭕ | 'before'은 정규식과 일치하는 'b'가 있으므로 | |
dude | 문자열 dude와 매치 ❌ | 'dude'는 정규식과 일치하는 문자 어떤 것도 없으므로 |
문자 클래스 안에 ^ 메타 문자를 사용할 경우엔 반대(not)의 의미를 갖습니다. 예를 들어, [^0-9]는 숫자가 아닌 문자만 매치됩니다.
정규 표현식 | 설명 |
---|---|
\d | 숫자와 매치, [0-9]와 동일한 표현식 |
\D | 숫자가 아닌 것과 매치, [^0-9]와 동일한 표현식 |
\s | whitespace 문자(space나 tab처럼 공백을 표현하는 문자와 매치, [ \t\n\r\f\v]와 동일한 표현식. 맨 앞은 공백을 의미한다. |
\S | whitespace 문자가 아닌 것과 매치. [^ \t\n\r\f\v] |
\w | 문자+숫자(alphanumeric)와 매치, [a-zA-Z0-9_]와 동일한 표현식이다. |
\W | 문자+숫자(alphanumeric)가 아닌 문자와 매치, [^a-zA-Z0-9_]와 동일한 표현식이다. |
정규 표현식의 Dot(.) 메타 문자는 줄바꿈 문자인 \n을 제외한 모든 문자와 매치됩니다.
다음 정규식을 봅시다.
a.b 👈 a와 b 사이에 줄바꿈 문자를 제외한 어떤 문자가 들어가도 모두 매치됨!
위 정규식의 의미는 아래와 같습니다.
"a + 모든 문자 + b"
즉, a와 b라는 문자 사이에 어떤 문자가 들어가도 모두 매치된다는 의미이다.
정규식[a.b] | 문자열 | 매치 여부 | 설명 |
---|---|---|---|
[a.b] | aab | 매치⭕ | 'aab'는 가운데 문자 'a'가 모든 문자를 의미하는 .과 일치하므로 정규식과 매치 |
a0b | 매치⭕ | 'a0b'는 가운데 문자 '0'이 모든 문자를 의미하는 .과 일치하므로 정규식과 매치 | |
abc | 매치❌ | 'abc'는 'a' 문자와 'b'문자 사이에 어떤 문자라도 하나 있어야 한다는 정규 표현식과 일치하지 않으므로 매치되지 않는다. |
다음 정규식을 봅시다.
a[.]b 👈 a와 b 사이에 Dot(.) 문자가 있으면 매치!
이게 무슨 소리일까요?
위의 정규식 a[.]b는 "a.b" 문자열과 매치되지만, "a0b"와는 매치되지 않습니다.
문자 클래스 안의 . 이 사용된 형식([.])이라면 이것은 '모든 문자'가 아닌 문자 .의 있는 그대로를 의미하니 주의합니다!
ca*t
👉 * 옆에 있는 a가 0번 이상 반복되면 매치
이 정규식에서 는 반복을 의미한다. 바로 옆에 있는 문자 a가 0부터 무한대로 반복할 수 있다는 의미이다.
정규식 | 문자열 | 매치 여부 | 설명 |
---|---|---|---|
ca*t | ct | 매치⭕ | 'a'가 0번 반복되어 매치 |
cat | 매치⭕ | 'a'가 1번 반복되어 매치 | |
caaat | 매치⭕ | 'a'가 3번 반복되어 매치 |
ca+t
반복을 나타내는 +도 있다. + 는 최소 1번 이상 반복될 때 사용한다.
정규식 | 문자열 | 매치 여부 | 설명 |
---|---|---|---|
ca+t | ct | 매치❌ | 'a'가 0번 반복되어 매치되지 않음 |
cat | 매치⭕ | 'a'가 1번 이상 반복되어 매치 | |
caaat | 매치⭕ | 'a'가 3번 이상 반복되어 매치 |
여기서 배우는 것은 반복 횟수를 지정해주고 싶을 때이다. 최소 1번 이상 3번 이하의 수를 반복하고 싶을 수 있다. 그럴 땐 {1,3}으로 표현이 가능하다.
이럴 때 { }를 사용하고 반복 횟수 고정이 가능하다. 만약 {3,}이면 반복 횟수가 3번 이상인 경우이며, {,3}일 때는 반복 횟수가 3 이하를 의미한다.
생략된 m은 0, 생략된 n은 무한대를 의미한다.
ca{2}t
위 정규식의 의미는 오른쪽과 같고, 정규식에 대한 매치 여부는 다음 표와 같다.
"c+a{반드시 2번 반복}+t"
정규식 | 문자열 | 매치 여부 | 설명 |
---|---|---|---|
ca{2}t | cat | 매치❌ | 'a'가 1번만 반복되어 매치되지 않음 |
caat | 매치⭕ | 'a'가 2번 반복되어 매치 |
cat{2,5}t
👉 a가 2~5번 반복되면 매치
"c+a(2~5번 반복)+t"
정규식 | 문자열 | 매치 여부 | 설명 |
---|---|---|---|
ca{2,5}t | cat | 매치❌ | 'a'가 1번만 반복되어 매치되지 않음 |
caat | 매치⭕ | 'a'가 2번 반복되어 매치 | |
caaaaat | 매치⭕ | 'a'가 5번 반복되어 매치 |
ab?c
👉 b가 0~1번 사용되면 매치
"a+b(있어도 되고 없어도 된다)+c"
개인적으로 있어도 되고 없어도 된다는게 '?' 자체를 의미하는 것 같아서 슬프네요. (과몰입)
정규식 | 문자열 | 매치 여부 | 설명 |
---|---|---|---|
ab?c | abc | 매치⭕ | 'b'가 1번만 사용되어 매치 |
ac | 매치⭕ | 'b'가 0번 반복되어 매치 |
, +, ? 메타 문자는 모두 {m,m} 형태로 고쳐 쓰는 것이 가능하지만 가급적 이해하기 쉽고 표현도 간결한 , +, ? 메타 문자를 사용하는 것이 좋습니다.