정규표현식(Regular Expression)은 문자열 속에서 특정한 패턴을 가진 문자열을 찾을 때 사용하는 것이다.
파이썬에서는 re 모듈을 통해 정규표현식을 제공한다. 그리고 주로 사용하는 4가지 메소드가 다음과 같다. 메소드의 파라미터가 각각 의미히는 것은 정규표현식, 찾을 문자열, 옵션이다.
Hello World라는 문자열에서 문자 o를 찾는다고 가정해보자.
import re
# 찾을 문자열
string = 'Hello World'
# 정규표현식
pattern = 'o'
result = re.findall(pattern, string)
print(result)
# 출력 결과는 ['o', 'o']
출력되는 결과는 두 개의 문자를 찾아낸다. 여기서 정규표현식을 ab로 입력하면 해당하는 문자가 없다는 결과를 반환한다.
정규표현식에서 사용하는 메타 문자에는 아래와 같은 것들이 있다.
. ^ $ * + ? { } [ ] \ | ( )
이 중에서 대괄호는 대괄호 사이에 있는 문자들 중 매치되는 문자 하나를 찾는 것이다. 하이픈(-)을 사용하면 범위를 나타내는데, 예를 들어 소문자는 [a-z], 대문자는 [A-Z]로 표현할 수 있다. 대소문자 전체는 [a-zA-Z]로 표현하면 된다.
Hello World, 1 2 3 4 5라는 문자열에서 소문자만 찾는다고 가정해보자.
import re
# 찾을 문자열
string = 'Hello World, 1 2 3 4 5'
# 정규표현식
pattern = '[a-z]'
result = re.findall(pattern, string)
print(result)
# 출력 결과는 ['e', 'l', 'l', 'o', 'o', 'r', 'l', 'd']
결과는 총 8개의 소문자를 찾아냈다. 이외에도 [0-9]로 표현하여 숫자 한 개를 찾아낼 수도 있다. 이처럼 대괄호는 사이에 존재하는 문자들 중 한 개를 찾아내는 것이다.
그렇다면 위에서 소개된 메타 문자를 찾고 싶을 땐 어떻게 할까? 프로그래밍을 조금 해보았다면 이스케이프 문자, 흔히 말하는 백슬래시(\)를 사용하면 된다고 예상할 수 있다. 하지만 파이썬에서는 문자열 리터럴 규칙에 의해 백슬래시를 이스케이프 문자로 인식하기 때문에 백슬래시 문자열 그대로 인식하게 하려면 백슬래시를 두 번 사용해야 한다.
예를 들어, 대괄호 문자를 찾는다고 가정해보자. 이때는 정규표현식을 [\\[\\]] 이런 식으로 사용해야 한다. 파이썬 리터럴 규칙에 의해 [\[\]] 이렇게 인식이 되고, 이를 정규표현식에서는 백슬래시 뒤 대괄호를 문자 그대로 인식하여 최종적으로 [[]] 이와 같은 패턴이 되는 것이다.
역슬래시를 찾으려면 [\\\\] 이렇게 역슬래시를 네 번 입력해야 한다. 그래야 파이썬 리터럴 규칙에 의해 [\\] 로 인식되고, 정규표현식에 의해 최종적으로 [\] 패턴으로 인식한다.
문자열 !@#$%^&*()_+<>/\[]에서 백슬래시와 대괄호를 찾아보도록 하자.
import re
# 찾을 문자열
string = '!@#$%^&*()_+<>/\[]'
# 정규표현식
pattern = '[\\\\\\[\\]]'
result = re.findall(pattern, string)
print(result)
# 출력 결과는 ['\\', '[', ']']
출력 결과를 보면 백슬래시는 파이썬에서 이스케이프가 필요하여 하나 더 붙었지만 대괄호는 그대로 출력되었다.
백슬래시를 여러 번 쓰는게 불편하여 파이썬에는 Raw String이라는 규칙이 생겼다. 이는 문자열 앞에
r을 붙여 해당 문자열에서 사용하는 백슬래시는 문자열 그대로임을 나타낼 때 사용한다.
예를 들어, 위 패턴'[\\\\\\[\\]]'은r'[\\\[\]]'이렇게 백슬래시를 한 번만 사용해도 된다. 파이썬에서의 이스케이프 처리가 필요없는 문자열이라는 의미이다.
\w : 특수 문자, 공백을 제외한 문자 한개를 찾을 때 사용한다.\W : 특수 문자, 공백만 찾을 때 사용한다.^) : [^a-z] 라는 정규표현식을 사용하면 소문자를 제외한 모든 글자 한 개를 찾는다. 즉, ^ 뒤에 오는 문자를 제외한 문자를 찾을 때 사용한다.^) : ^뒤에 오는 문자가 문자열의 처음부분에 있는지 검사할 때 사용한다. ^[a-z]는 문자열 처음에 소문자가 있는지 검사한다.$) : $앞에 있는 문자가 문자열의 마지막부분에 있는지 검사할 때 사용한다. [a-z]$는 문자열 끝에 소문자가 있는지 검사한다..) : 점은 공백을 포함한 모든 문자 한 개를 찾을 때 사용한다.+ 문자는 한 개 이상의 문자가 반복되는지 검사한다. [a-z]+는 한 개 이상의 소문자 문자열을 찾을 때 사용한다.
import re
# 찾을 문자열
string = 'Helo, World. !@#$%^&*()_+<>/\[]'
# 정규표현식
pattern = '[a-z]+'
result = re.findall(pattern, string)
print(result)
# 출력 결과는 ['elo', 'orld']
찾고자 하는 문자열 길이를 지정할 때 중괄호({})를 사용한다. [a-z0-9,]{3} 패턴은 소문자, 숫자, 쉼표가 세 개 일치하는 문자를 찾는 것이다.
import re
# 찾을 문자열
string = 'Helo, World. 1,2,3,4,5 !@#$%^&*()_+<>/\[]'
# 정규표현식
pattern = '[a-z0-9,]{3}'
result = re.findall(pattern, string)
print(result)
# 출력 결과는 ['elo', 'orl', '1,2', ',3,', '4,5']
중괄호 안에 숫자를 두 개 입력하면 최소, 최대길이를 의미하는 것이다. 예를 들어, [a-z0-9,]{3,6} 은 문자열의 최소 길이가 3, 최대 길이가 6인 문자열을 검색하는 패턴이다.
이 외에도 많은 정규표현식이 있지만 기본적인 규칙에 대해서만 다루었다. 프로젝트를 진행하다가 더 깊은 내용을 다루게 되면 그때 공부 겸 포스팅을 하도록 하겠다.