정규 표현식(Regular Expressions)은 문자열을 처리할 때 사용한다. 줄여서 정규식이라고 한다. 이 표현을 배우면 문자열을 아주 효율적으로 다룰 수 있는 파워풀한 기술을 가지게 된다.
정규식을 배우기 위해서는 메타 문자(Meta Characters)에 대해 알아야 한다.
. ^ $ * + ? { } [ ] \ | ( )
파이썬은 정규 표현식을 지원하는 라이브러리인 re(Regular Expression) 모듈이 있다. 이를 사용하여 정규식에 대해 알아보자. re는 크게 4가지 함수를 제공한다.
Method | 설명 |
match() | 문자열의 처음부터 정규식과 매치되는지 조사, 객체로 반환 |
search() | 문자열 전체를 검색하여 정규식과 매치되는지 조사, 객체로 반환 |
findall() | 정규식과 매치되는 모든 문자열(substring)을 리스트로 반환 |
finditer() | 정규식과 매치되는 모든 문자열(substring)을 반복 가능한 객체로 반환 |
[표1.3] re가 제공하는 함수 |
1) [ ]
정규식이 [abc]라면 문자열에 a, b, c 중 한 개의 문자와 매치되는 문자열을 뜻한다. 하이픈(-)을 추가하면 범위를 의미한다.
- [a-zA-Z]: 알파벳 모두
- [0-9]: 숫자
- [^0-9]: 숫자가 아닌 것
위와 같이 자주 사용하는 정규식은 다음과 같은 표현식으로도 쓰인다.
\d – 숫자와 매치. [0-9]와 동일한 표현식
\D – 숫자가 아닌 것과 매치. [^0-9]와 동일한 표현식
\s - whitespace 문자와 매치, [ \t\n\r\f\v]와 동일한 표현식(빈 칸은 공백문자)
\S - whitespace 문자가 아닌 것과 매치, [^ \t\n\r\f\v]와 동일한 표현식
\w - 문자+숫자(alphanumeric)와 매치, [a-zA-Z0-9_]와 동일한 표현식
\W - 문자+숫자(alphanumeric)가 아닌 문자와 매치, [^a-zA-Z0-9_]와 동일한 표현식
import re
r_e = re.compile('[abc]')
result = r_e.match('bww')
print(result)
result = r_e.search('wbw')
print(result)
result = r_e.findall('wbwba')
print(result)
result = r_e.finditer('wbwba')
print(result)
for r in result:
print(r)
결과 값
<re.Match object; span=(0, 1), match='b'>
<re.Match object; span=(1, 2), match='b'>
['b', 'b', 'a']
<callable_iterator object at 0x000000000295D388>
<re.Match object; span=(1, 2), match='b'>
<re.Match object; span=(3, 4), match='b'>
<re.Match object; span=(4, 5), match='a'>
Match 객체에 대한 함수는 다음과 같다. group()은 매치된 문자열을 보여준다. start(), end(), span()은 매치된 문자열의 시작과 끝을 보여준다.
import re
r_e = re.compile('[abc]')
result = r_e.search('ssbww')
print(result)
print(result.group())
print(result.start())
print(result.end())
print(result.span())
결과 값
<re.Match object; span=(2, 3), match='b'>
b
2
3
(2, 3)
2) .
Dot(.)은 \n를 제외한 모든 문자와 매치된다. b.a는 b + “모든 문자” + a를 의미한다. 순수 Dot(.)을 매치시키기 위해서는 b[.]a라는 표현식을 쓰면 된다.
import re
r_e = re.compile('a.b')
result = r_e.search('avsvasbddfbss')
print(result)
결과 값
<re.Match object; span=(4, 7), match='asb'>
3) *
*는 반복을 의미한다. ab*t는 at, abt, abbt, abbbt 등과 매치된다.
import re
r_e = re.compile('ab*t')
result = r_e.search('wwatavsvasbddfbss')
print(result)
결과 값
<re.Match object; span=(2, 4), match='at'>
4) +
+도 반복을 의미한다. *와 다른 점은 반복 횟수가 1이상인 것만 매치된다. ab*t는 abt, abbt, abbbt 등과 매치된다.
import re
r_e = re.compile('ab+t')
result = r_e.search('wwabbtavsvasbddfbss')
print(result)
결과 값
<re.Match object; span=(2, 6), match='abbt'>
5) {m, n}
반복 횟수를 정할 수 있다. {0,}는 0번 이상 반복 {,2}는 2번 이하 반복, {1,3}은 1~3번 반복, {5}는 반드시 5번 반복을 의미한다. ab{3,4}t는 abbbt, abbbbt와 매치된다.
import re
r_e = re.compile('ab{3,4}t')
result = r_e.search('wwaabbbtbddfbss')
print(result)
결과 값
<re.Match object; span=(3, 8), match='abbbt'>
6) ?
?는 있어도 되고 없어도 된다. ab?c는 ac, abc와 매치된다.
import re
r_e = re.compile('ab?t')
result = r_e.search('wwaatbbbtbddfbss')
print(result)
결과 값
<re.Match object; span=(3, 5), match='at'>
7) |
or을 의미한다. abc|def는 abc나 def와 매치된다.
import re
r_e = re.compile('ab|t')
result = r_e.findall('wwabatbbbtbddfbss')
print(result)
결과 값
['ab', 't', 't']
8) ^
^는 문자열의 처음부분만 매치한다. 예를 들어 ^love라고 한다면 문자열의 처음이 반드시 love로 시작해야 한다. \^를 사용하면 ^문자 그 자체를 매치한다.
import re
r_e = re.compile('^love')
result = r_e.search('loveislove')
print(result)
결과 값
<re.Match object; span=(0, 4), match='love'>
9) $
$는 문자열의 끝부분만 매치한다. 예를 들어 love$라고 한다면 문자열의 끝이 반드시 love로 끝나야 한다. \$를 사용하면 $문자 그 자체를 매치한다.
import re
r_e = re.compile('love$')
result = r_e.search('loveislove')
print(result)
결과 값
<re.Match object; span=(6, 10), match='love'>
10) \b
whitespace로 구분된 문자열을 매치한다. \babc\b는 ee abc ee처럼 양쪽에 공백이 있는 abc와 매치된다. 주의할 점은 \b는 파이썬 리터럴 규칙에 의해 백스페이스를 의미하므로 정규식 앞에 r문자를 넣어 raw string임을 알려주자.
import re
r_e = re.compile(r'\babc\b')
result = r_e.search('love abc love')
print(result)
결과 값
<re.Match object; span=(5, 8), match='abc'>
11) \B
whitespace로 구분된 문자열이 아닌 경우 매치한다. \Babc\B는 gggabcg처럼 공백이 없는 abc와 매치된다.
import re
r_e = re.compile(r'\Babc\B')
result = r_e.search('loveabclove')
print(result)
결과 값
<re.Match object; span=(4, 7), match='abc'>
12) \A
^와 동일하게 문자열의 처음부분만 매치한다. 차이점은 re.MULTILINE 옵션을 사용한 경우 ^는 각 줄의 문자열의 처음부분을 매치하지만 \A는 전체 문자열의 처음부분만 매치한다.
import re
str = """loveabclove
loveabclove
loveabclove"""
r_e = re.compile(r'\Alove', re.MULTILINE)
result = r_e.findall(str)
print(result)
r_e = re.compile(r'^love', re.MULTILINE)
result = r_e.findall(str)
print(result)
결과 값
['love']
['love', 'love', 'love']
13) \Z
$와 동일하게 문자열의 끝부분만 매치한다. 차이점은 re.MULTILINE 옵션을 사용한 경우 $는 각 줄의 문자열의 끝부분을 매치하지만 \Z는 전체 문자열의 끝부분만 매치한다.
import re
str = """abclove
abclove
abclove"""
r_e = re.compile(r'love\Z', re.MULTILINE)
result = r_e.findall(str)
print(result)
r_e = re.compile(r'love$', re.MULTILINE)
result = r_e.findall(str)
print(result)
결과 값
['love']
['love', 'love', 'love']
MULTILINE과 같은 컴파일 옵션은 몇 가지 더 있다.
옵션 | 의미 |
DOTALL, S | Dot(.)이 줄바꿈 문자(\n)를 포함하여 모든 문자와 매치 가능 |
IGNORECASE, I | 대소문자에 관계없이 매치 가능 |
MULTILINE, M | 여러줄과 매치 가능 |
VERBOSE, X | verbose 모드를 사용(주석을 사용하여 가독성을 높임, 컴파일시 whitespace와 #주석을 제거해줌) |
[표1.4] re 컴파일 옵션 |
14) ( )
문자열을 그룹핑할 수 있다. (abc)+는 abc라는 문자열이 1번 이상 반복되는 경우와 매치된다.
import re
r_e = re.compile('(ABC)+')
result = r_e.search('aa ABCABC ABC ABCABC ssbww')
print(result)
결과 값
<re.Match object; span=(3, 9), match='ABCABC'>
'Programming > Python' 카테고리의 다른 글
[01. Python] 013. 예외처리 (0) | 2020.01.02 |
---|---|
[01. Python] 012. 클래스 (0) | 2020.01.02 |
[01. Python] 011. 함수 (0) | 2019.12.30 |
[01. Python] 010. 제어문 – while (0) | 2019.12.29 |
[01. Python] 009. 제어문 – for (0) | 2019.12.29 |