regular expression
: 특정한 패턴과 일치하는 문자열을 '검색', '치환', '제거'하는 기능을 지원
raw string
문자열 앞에 r이 붙은면 해당 문자열이 구성된 그대로 문자열로 반환
a = 'abcdef\n'
print(a)
b = r'abcdef\n'
print(b)
abcdef
abcdef\n
import re
첫 번째로 패턴을 찾으면 match 객체를 반환한다.
패턴을 찾지 못하면 None 반환
re.search(r'abd','123abdef')
<re.Match object; span = (3, 6), match = 'abd'>
metacharacters(메타 캐릭터)
[] 문자들의 범위를 나타내기 위해 사용한다.
ex)
m = re.search(r'[cmb]at', 'aat')
print(m)
# 결과 : m
re.search(r'[0-7]haha', '7hahah')
# 결과 : <re.Match object; span = (0, 5), match = '7haha'>
re.search(r'[abc.^]aron', 'baron')
# 결과 : <re.Match object; span=(0,5), match = 'baron'>
m = re.search(r'[^abc]aron', 'baron')
# 결과 : None
re.search(r'p.g','pig')
# 결과 : <re.Match object; span = (0,3), match='pig'>
\
다른 문자와 함께 사용되어 특수한 의미로 사용
[^0-9]
와 동일[^0-9a-zA-Z]
와 동일메타 캐릭터가 캐릭터 자체를 표현하도록 할 경우 사용한다.
re.search(r'\d\d\d\w', '112abcdef119')
# 결과 : <re.Match object; span = (0,4), match = '112a'>
re.search(r'..\w\w', '@#$%ABCDabcd')
# 결과 : <re.Match object; span=(2,6), match='$%AB'>
re.search(r'\Sand', 'apple land banana')
# 결과 : <re.Match object; span=(6,10), match='land'>
re.search(r'\.and', '.and')
# 결과 : <re.Match object; span=(0,4), match='.and'>
패턴 뒤에 위치하는 *, +, ?는 해당 패턴이 반복적으로 존재하는지 검사
반복 패턴의 경우 greedy하게 검색한다.
가능한 많은 부분이 매칭되도록 한다.
re.search(r'a[bcd]*b', 'abcbdccb')
# 결과 : <re.Match object; span=(0,8), match='abcbdccb'>
re.search(r'http?', 'http://www.naver.com')
# 결과 : <re.Match object; span=(0,4), match='http'>
()을 사용하여 그루핑. 매칭 결과를 각 그룹별로 분리 가능
패턴 명시 할 때, 각 그룹을 괄호() 안에 넣어 분리하여 사용
m = re.search(r'(\w+)@(.+)','test@gmail.com')
print(m.group(1))
print(m.group(2))
print(m.group(0))
# 결과 :
# test
# gmail.com
# test@gmail.com
*, +, ?을 사용하여 반복적인 패턴을 찾는 것이 가능하나, 반복의 횟수 제한은 불가
패턴뒤에 위치하는 중괄호{}에 숫자를 명시하면 해당 숫자 만큼의 반복인 경우에만 매칭
{4} : 4번 반복
{3, 4} : 3 ~ 4번 반복
re.search('pi{3,5}g','piiiiig')
# 결과 : <re.Match object; span=(0,7), match='piiiing'>
{m, n}의 경우 m번에서 n번 반복하나 greedy하게 동작
{m,n}?로 사용하면 non-greedy하게 동작, 즉 최소 m번만 매칭하면 만족
re.search(r'a{3,5}','aaaaa')
# 결과 : <re.Match object; span=(0,5), match='aaaaa'>
re.search(r'a{3,5}?','aaaaa')
# 결과 : <re.Match object; span=(0,3), match='aaa'>
search와 유사하나, 주어진 문자열의 시작부터 비교하여 패턴이 있는지 확인
시작부터 해당 패턴이 존재하지 않는다면 None 반환
search가 최초로 매칭되는 패턴만 반환한다면, findall은 매칭되는 전체의 패턴을 반환
매칭되는 모든 결과를 리스트 형태로 반환
re.findall(r'[\w-]+@[\w.]+', 'test@gmail.com haha test2@gmail.com nice test test')
# 결과 : ['test@gmail.com','test2@gmail.com']
sub(정규표현식, 대체할 문자(열), 전체 문자열)
주어진 문자열에서 일치하는 모든 패턴을 replace
그 결과를 문자열로 다시 반환한다.
두 번째 인자는 특정 문자열이 될 수도 있고, 함수가 될 수도 있다.
count가 0인 경우는 전체를 1이상이면 해당 숫자만큼 치환된다.
re.sub(r'[\w-]+@[\w.]+', 'great', 'test@gmail.com haha test2@gmail.com nice test test', count=1)
# 결과 : great haha test2@gmail.com nice test test
동일한 정규표현식을 매번 다시 쓰기 번거러움을 해결
compile로 해당 표현식을 re.RegexObject 객체로 저장하여 사용가능
email_reg = re.compile(r'[\w-]+@[\w.]+')
email_reg.search('test@gmail.com haha good')
# 결과 : <re.Match object; span(0, 14), match='test@gmail.com'
ex)
2단계: ^ 문자를 이용해 반대 조건에 해당하는 문자를 빈 문자열로 치환한다.
re.sub(r'[^a-z0-9-_.]', '', new_id)
3단계: {2,}를 이용해 2번 이상 반복되는 것을 찾아내어 . 문자로 치환한다.
re.sub(r'[.]{2,}', '.', new_id)
4단계: ^ 문자로 처음 위치를, $ 문자로 끝 위치의 . 문자를 찾아내어 빈 문자열로 치환한다.
re.sub(r'^[.]|[.]$', '', new_id)
6단계: [:15]를 이용해 16자 미만의 문자만 추출해내고, $ 문자로 끝 위치의 . 문자를 찾아내어 빈 문자열로 치환한다.
re.sub(r'[.]$', '', new_id[:15])
참고 자료