파이썬 정규표현식 마스터하기: 실전 가이드
정규표현식(Regular Expression)은 특수한 문자 시퀀스로, 패턴에 보관된 특수 구문을 사용하여 다른 문자열 또는 문자열 집합을 매칭하거나 찾는 데 도움을 줍니다. 정규표현식은 UNIX 세계에서 널리 사용됩니다.
파이썬 모듈 re는 파이썬에서 Perl 스타일의 정규표현식을 완벽하게 지원합니다. 정규표현식을 컴파일하거나 사용하는 동안 오류가 발생하면 re 모듈은 re.error 예외를 발생시킵니다.
정규표현식을 처리하는 데 사용되는 두 가지 중요한 함수를 다룰 것입니다. 하지만 먼저 한 가지: 정규표현식에서 사용될 때 특수한 의미를 가지는 다양한 문자가 있습니다. 정규표현식을 다룰 때 혼란을 피하기 위해 r'expression' 형태의 Raw String을 사용하겠습니다.
match 함수
이 함수는 선택적 flags와 함께 RE pattern을 string의 시작 부분에서 매칭을 시도합니다.
이 함수의 구문은 다음과 같습니다.
re.match(pattern, string, flags=0)
매개변수 설명은 다음과 같습니다.
| 번호 |
매개변수 및 설명 |
| 1 |
pattern 매칭할 정규표현식입니다. |
| 2 |
string 패턴을 문자열의 시작 부분에서 매칭하기 위해 검색할 문자열입니다. |
| 3 |
flags 비트별 OR(|)를 사용하여 다양한 플래그를 지정할 수 있습니다. 이들은 아래 표에 나열된 수정자입니다. |
re.match 함수는 성공 시 match 객체를, 실패 시 None을 반환합니다. match 객체의 group(num) 또는 groups() 함수를 사용하여 매칭된 표현식을 얻을 수 있습니다.
| 번호 |
Match 객체 메서드 및 설명 |
| 1 |
group(num=0) 전체 매칭(또는 특정 서브그룹 num)을 반환합니다. |
| 2 |
groups() 모든 매칭되는 서브그룹을 튜플로 반환합니다(없으면 빈 튜플). |
예제
#!/usr/bin/python
import re
line = "Cats are smarter than dogs"
matchObj = re.match(r'(.*) are (.*?) .*', line, re.M | re.I)
if matchObj:
print("matchObj.group() : ", matchObj.group())
print("matchObj.group(1) : ", matchObj.group(1))
print("matchObj.group(2) : ", matchObj.group(2))
else:
print("No match!!")
위 코드를 실행하면 다음과 같은 결과가 나옵니다.
matchObj.group() : Cats are smarter than dogs
matchObj.group(1) : Cats
matchObj.group(2) : smarter
search 함수
이 함수는 선택적 flags와 함께 RE pattern을 string 내에서 첫 번째 발생 위치를 검색합니다.
이 함수의 구문은 다음과 같습니다.
re.search(pattern, string, flags=0)
매개변수 설명은 다음과 같습니다.
| 번호 |
매개변수 및 설명 |
| 1 |
pattern 매칭할 정규표현식입니다. |
| 2 |
string 문자열 어디에서든 패턴을 매칭하기 위해 검색할 문자열입니다. |
| 3 |
flags 비트별 OR(|)를 사용하여 다양한 플래그를 지정할 수 있습니다. 이들은 아래 표에 나열된 수정자입니다. |
re.search 함수는 성공 시 match 객체를, 실패 시 none을 반환합니다. match 객체의 group(num) 또는 groups() 함수를 사용하여 매칭된 표현식을 얻을 수 있습니다.
| 번호 |
Match 객체 메서드 및 설명 |
| 1 |
group(num=0) 전체 매칭(또는 특정 서브그룹 num)을 반환합니다. |
| 2 |
groups() 모든 매칭되는 서브그룹을 튜플로 반환합니다(없으면 빈 튜플). |
예제
#!/usr/bin/python
import re
line = "Cats are smarter than dogs"
searchObj = re.search(r'(.*) are (.*?) .*', line, re.M | re.I)
if searchObj:
print("searchObj.group() : ", searchObj.group())
print("searchObj.group(1) : ", searchObj.group(1))
print("searchObj.group(2) : ", searchObj.group(2))
else:
print("Nothing found!!")
위 코드를 실행하면 다음과 같은 결과가 나옵니다.
searchObj.group() : Cats are smarter than dogs
searchObj.group(1) : Cats
searchObj.group(2) : smarter
매칭 vs 검색
파이썬은 정규표현식을 기반으로 두 가지 다른 기본 연산을 제공합니다: match는 문자열 시작 부분에서만 매칭을 확인하는 반면, search는 문자열 어디에서든 매칭을 확인합니다(이것이 Perl의 기본 동작입니다).
예제
#!/usr/bin/python
import re
line = "Cats are smarter than dogs"
matchObj = re.match(r'dogs', line, re.M | re.I)
if matchObj:
print("match --> matchObj.group() : ", matchObj.group())
else:
print("No match!!")
searchObj = re.search(r'dogs', line, re.M | re.I)
if searchObj:
print("search --> searchObj.group() : ", searchObj.group())
else:
print("Nothing found!!")
위 코드를 실행하면 다음과 같은 결과가 나옵니다.
No match!!
search --> searchObj.group() : dogs
검색 및 치환
정규표현식을 사용하는 가장 중요한 re 메서드 중 하나는 sub입니다.
구문
re.sub(pattern, repl, string, max=0)
이 메서드는 string에서 RE pattern의 모든 발생을 repl로 치환합니다. max가 제공되지 않으면 모든 발생을 치환합니다. 이 메서드는 수정된 문자열을 반환합니다.
예제
#!/usr/bin/python
import re
phone = "2004-959-559 # This is Phone Number"
# 파이썬 스타일 주석 삭제
num = re.sub(r'#.*$', "", phone)
print("Phone Num : ", num)
# 숫자가 아닌 모든 것 제거
num = re.sub(r'\D', "", phone)
print("Phone Num : ", num)
위 코드를 실행하면 다음과 같은 결과가 나옵니다.
Phone Num : 2004-959-559
Phone Num : 2004959559
정규표현식 수정자: 옵션 플래그
정규표현식 리터럴에는 매칭의 다양한 측면을 제어하는 선택적 수정자가 포함될 수 있습니다. 수정자는 선택적 플래그로 지정됩니다. 앞서 보여준 것처럼 배타적 OR(|)를 사용하여 여러 수정자를 제공할 수 있으며, 다음 중 하나로 표현될 수 있습니다.
| 번호 |
수정자 및 설명 |
| 1 |
re.I 대소문자 구분 없이 매칭을 수행합니다. |
| 2 |
re.L 현재 로케일에 따라 단어를 해석합니다. 이 해석은 알파벳 그룹(\w와 \W)과 단어 경계 동작(\b와 \B)에 영향을 줍니다. |
| 3 |
re.M $가 문자열 끝이 아닌 줄 끝과 매칭되게 하고, ^가 문자열 시작이 아닌 모든 줄의 시작과 매칭되게 합니다. |
| 4 |
re.S 마침표(점)가 개행 문자를 포함한 모든 문자와 매칭되게 합니다. |
| 5 |
re.U 유니코드 문자 집합에 따라 문자를 해석합니다. 이 플래그는 \w, \W, \b, \B의 동작에 영향을 줍니다. |
| 6 |
re.X "더 예쁜" 정규표현식 구문을 허용합니다. 공백을 무시합니다(문자 집합 [] 내부나 백슬래시로 이스케이프된 경우 제외) 및 이스케이프되지 않은 #을 주석 마커로 처리합니다. |
정규표현식 패턴
제어 문자 (+ ? . * ^ $ ( ) [ ] { } | \)를 제외하고 모든 문자는 자기 자신과 매칭됩니다. 제어 문자는 백슬래시로 이스케이프할 수 있습니다.
다음 표는 파이썬에서 사용 가능한 정규표현식 구문을 나열합니다.
| 번호 |
패턴 및 설명 |
| 1 |
^ 줄의 시작과 매칭. |
| 2 |
$ 줄의 끝과 매칭. |
| 3 |
. 개행 문자를 제외한 임의의 단일 문자와 매칭. m 옵션 사용 시 개행 문자도 매칭. |
| 4 |
[...] 대괄호 안의 임의의 단일 문자와 매칭. |
| 5 |
[^...] 대괄호 안에 없는 임의의 단일 문자와 매칭. |
| 6 |
re* 앞의 표현식의 0회 이상 발생과 매칭. |
| 7 |
re+ 앞의 표현식의 1회 이상 발생과 매칭. |
| 8 |
re? 앞의 표현식의 0회 또는 1회 발생과 매칭. |
| 9 |
re{ n} 앞의 표현식이 정확히 n번 발생과 매칭. |
| 10 |
re{ n,} 앞의 표현식이 n번 이상 발생과 매칭. |
| 11 |
re{ n, m} 앞의 표현식이 최소 n번 최대 m번 발생과 매칭. |
| 12 |
a| b a 또는 b와 매칭. |
| 13 |
(re) 정규표현식을 그룹화하고 매칭된 텍스트를 기억. |
| 14 |
(?imx) 정규표현식 내에서 i, m, x 옵션을 일시적으로 켭니다. 괄호 안에 있으면 해당 영역만 영향. |
| 15 |
(?-imx) 정규표현식 내에서 i, m, x 옵션을 일시적으로 끕니다. 괄호 안에 있으면 해당 영역만 영향. |
| 16 |
(?: re) 매칭된 텍스트를 기억하지 않고 정규표현식을 그룹화. |
| 17 |
(?imx: re) 괄호 내에서 i, m, x 옵션을 일시적으로 켭니다. |
| 18 |
(?-imx: re) 괄호 내에서 i, m, x 옵션을 일시적으로 끕니다. |
| 19 |
(?#...) 주석. |
| 20 |
(?= re) 패턴을 사용하여 위치를 지정. 범위가 없음. |
| 21 |
(?! re) 패턴 부정을 사용하여 위치를 지정. 범위가 없음. |
| 22 |
(?> re) 백트래킹 없이 독립적인 패턴과 매칭. |
| 23 |
\w 단어 문자와 매칭. |
| 24 |
\W 비단어 문자와 매칭. |
| 25 |
\s 공백과 매칭. [\t\n\r\f]와 동일. |
| 26 |
\S 비공백과 매칭. |
| 27 |
\d 숫자와 매칭. [0-9]와 동일. |
| 28 |
\D 비숫자와 매칭. |
| 29 |
\A 문자열의 시작과 매칭. |
| 30 |
\Z 문자열의 끝과 매칭. 개행이 있으면 개행 직전과 매칭. |
| 31 |
\z 문자열의 끝과 매칭. |
| 32 |
\G 마지막 매칭이 끝난 지점과 매칭. |
| 33 |
\b 대괄호 밖에서 단어 경계와 매칭. 대괄호 안에서 백스페이스(0x08)와 매칭. |
| 34 |
\B 비단어 경계와 매칭. |
| 35 |
\n, \t, 등 개행, 캐리지 리턴, 탭 등과 매칭. |
| 36 |
\1...\9 n번째 그룹화된 부분표현식과 매칭. |
| 37 |
\10 이미 매칭되었다면 n번째 그룹화된 부분표현식과 매칭. 그렇지 않으면 문자 코드의 8진수 표현을 참조. |
정규표현식 예제
리터럴 문자
| 번호 |
예제 및 설명 |
| 1 |
python "python"과 매칭. |
문자 클래스
| 번호 |
예제 및 설명 |
| 1 |
[Pp]ython "Python" 또는 "python"과 매칭 |
| 2 |
rub[ye] "ruby" 또는 "rube"와 매칭 |
| 3 |
[aeiou] 임의의 소문자 모음 하나와 매칭 |
| 4 |
[0-9] 임의의 숫자와 매칭; [0123456789]와 동일 |
| 5 |
[a-z] 임의의 소문자 ASCII 문자와 매칭 |
| 6 |
[A-Z] 임의의 대문자 ASCII 문자와 매칭 |
| 7 |
[a-zA-Z0-9] 위의 모든 것과 매칭 |
| 8 |
[^aeiou] 소문자 모음이 아닌 모든 것과 매칭 |
| 9 |
[^0-9] 숫자가 아닌 모든 것과 매칭 |
특수 문자 클래스
| 번호 |
예제 및 설명 |
| 1 |
. 개행 문자를 제외한 모든 문자와 매칭 |
| 2 |
\d 숫자 매칭: [0-9] |
| 3 |
\D 비숫자 매칭: [^0-9] |
| 4 |
\s 공백 문자 매칭: [ \t\r\n\f] |
| 5 |
\S 비공백 매칭: [^ \t\r\n\f] |
| 6 |
\w 단일 단어 문자 매칭: [A-Za-z0-9_] |
| 7 |
\W 비단어 문자 매칭: [^A-Za-z0-9_] |
반복 케이스
| 번호 |
예제 및 설명 |
| 1 |
ruby? "rub" 또는 "ruby" 매칭: y는 선택적 |
| 2 |
ruby* "rub"에 0개 이상의 y |
| 3 |
ruby+ "rub"에 1개 이상의 y |
| 4 |
\d{3} 정확히 3자리 숫자 매칭 |
| 5 |
\d{3,} 3자리 이상 숫자 매칭 |
| 6 |
\d{3,5} 3, 4, 또는 5자리 숫자 매칭 |
비탐욕적 반복
가장 적은 반복 횟수와 매칭합니다.
| 번호 |
예제 및 설명 |
| 1 |
<.*> 탐욕적 반복: "<python>perl>"와 매칭 |
| 2 |
<.*?> 비탐욕적: "<python>perl>"에서 "<python>"과 매칭 |
괄호를 사용한 그룹화
| 번호 |
예제 및 설명 |
| 1 |
\D\d+ 그룹 없음: +가 \d 반복 |
| 2 |
(\D\d)+ 그룹화됨: +가 \D\d 쌍 반복 |
| 3 |
([Pp]ython(, )?)+ "Python", "Python, python, python" 등 매칭 |
역참조
이전에 매칭된 그룹을 다시 매칭합니다.
| 번호 |
예제 및 설명 |
| 1 |
([Pp])ython&\1ails python&pails 또는 Python&Pails 매칭 |
| 2 |
(['"])[^\1]*\1 작은따옴표 또는 큰따옴표 문자열. \1은 1번째 그룹이 매칭한 것과 매칭. \2는 2번째 그룹이 매칭한 것과 매칭 등. |
대안
| 번호 |
예제 및 설명 |
| 1 |
python|perl "python" 또는 "perl" 매칭 |
| 2 |
rub(y|le) "ruby" 또는 "ruble" 매칭 |
| 3 |
Python(!+|\?) "Python" 뒤에 하나 이상의 ! 또는 하나의 ? |
앵커
매칭 위치를 지정해야 합니다.
| 번호 |
예제 및 설명 |
| 1 |
^Python 문자열 또는 내부 줄 시작에서 "Python" 매칭 |
| 2 |
Python$ 문자열 또는 줄 끝에서 "Python" 매칭 |
| 3 |
\APython 문자열 시작에서 "Python" 매칭 |
| 4 |
Python\Z 문자열 끝에서 "Python" 매칭 |
| 5 |
\bPython\b 단어 경계에서 "Python" 매칭 |
| 6 |
\brub\B \B는 비단어 경계: "rube"와 "ruby"에서 "rub" 매칭하지만 단독으로는 매칭 안 함 |
| 7 |
Python(?=!) "Python" 매칭, 뒤에 느낌표가 오는 경우 |
| 8 |
Python(?!!) "Python" 매칭, 뒤에 느낌표가 오지 않는 경우 |
괄호를 사용한 특수 구문
| 번호 |
예제 및 설명 |
| 1 |
R(?#comment) "R" 매칭. 나머지는 주석 |
| 2 |
R(?i)uby "uby" 매칭 시 대소문자 무시 |
| 3 |
R(?i:uby) 위와 동일 |
| 4 |
rub(?:y|le) \1 백레퍼런스 생성 없이 그룹화만 |