정규 표현식(Regular Expressions), 정규식
- 복잡한 문자열을 처리할 때 사용하는 기법
- 파이썬 뿐 아니라 문자열을 처리하는 모든 곳에서 사용
- 정규식을 사용하면 찾거나 바꿔야 할 문자열의 규칙이 복잡하더라도 코드를 간결히 줄일 수 있다.
정규 표현식 기초
정규식에는 다음의 문자가 특별한 용도로 사용된다. *메타문자 라고도 부름
. ^ $ * + ? { } [ ] \ | ( )
문자 클래스 [ ]
- [ ] 사이 문자들과 매치
- [123] 이라면, 1, 2, 3 중 하나의 문자와 매치를 의미.
- 하이픈 "-" 을 사용 [1-3] 으로 동일하게 표현 가능
예) 정규식 [19] 표현 으로 정규식 sub 매서드를 사용, data 문자열에서 1과 9가 있다면 "교"로 교체
#문자 클래스 []
data = '''
zunon1979sputnik7565
'''
s_data = re.sub("[19]", "교", data)
print(s_data)
#sub 정규식과 매치되면 변경시킴, str타입으로 반환.
#re.sub(pattern, replace, string, count=0, flag=0)
#pattern과 일치하는 모든것을 relpace로 교체, count는 최대 몇번까지 교체할 것인가를 설정.
zunon교교7교sputnik7565
*pattern은 정규식을 컴파일한 결과
예) 정규식 [1-9] 표현으로 1부터 9까지 숫자가 있다면 "교"로 교체
#문자 클래스 [ - ]
data = '''
zunon1979sputnik7565
'''
s_data = re.sub("[1-9]", "교", data)#"-" 하이픈을 사용하면 두 문자 사이의 범위를 의미, 즉 5,6,7
print(s_data)
zunon교교교교sputnik교교교교
자주 사용하는 문자 클래스
정규식 | 설명 |
\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_]와 동일한 표현식 |
Dot(.)
- . 은 줄바꿈 문자 \n을 제외한 모든 문자와 매치를 의미한다.
- a.b 는 a와 b사이 어떤 문자가 들어가도 모두 매치란 의미
예)
#Dot(.)
data = '''
zunon1979sputnik7565 sppppik7565
'''
s_data = re.sub("1.7", "교", data)
s_data2 = re.sub("s.....k", "교", data)
print(s_data)
print(s_data2)
zunon교9sputnik7565 sppppik7565 #1과 7사이에 어떤 수가 있던지 1979 중 197을 찾아 반환
zunon1979교7565 교7565 #s.....k사이에 어떤 문자가 있건 자리수가 맞으면 반환
반복(*)
- * 은 반복을 의미하는 메타문자로 * 바로 앞에 있는 문자가 0개부터 무한대로 반복 될 수 있다는 의미.
#반복(*)
data = '''
sputnik, spuuuutnik, suputnik, spootniiiiiik, sports, spot, slot
'''
s_data = re.sub("spu*", "교", data) #sp를 포함하면 u는 0든 무한대든 모두 반환
s_data2 = re.sub("ni*k", "교", data) #n을 포함하면 i가 몇개든 모두 반환
print(s_data)
print(s_data2)
교tnik, 교tnik, suputnik, 교ootniiiiiik, 교orts, 교ot, slot
sput교, spuuuut교, suput교, spoot교, sports, spot, slot
반복(+)
- + 은 반복을 의미하는 메타문자로 + 바로 앞에 있는 문자가 최소 1개부터 무한대로 반복 될 수 있다는 의미.
#반복(+)
data = '''
sputnik, spuuuutnik, suputnik, spootniiiiiik, sports, spot, slot
'''
s_data = re.sub("spu+", "교", data) #sp를 포함하면 u는 최소 1개부터 모두 반환
s_data2 = re.sub("ni+k", "교", data) #n을 포함하면 i는 최소 1개부터 모두 반환
print(s_data)
print(s_data2)
교tnik, 교tnik, suputnik, spootniiiiiik, sports, spot, slot
sput교, spuuuut교, suput교, spoot교, sports, spot, slot
반복({m,n),?)
- 반복 횟수를 제한하고 싶을 때 사용. {m.n}정규식은 m부터 n까지의 반복횟수를 매치, m이나 n을 생략 가능.
- {5, }라면 5회 이상, { .5}라면 5회 이하
예) {m,n}
#정규식 {m,n}을 활용한 반복횟수 지정
data = '''
sputnik,spuutnik,spuuutnik,spuuuutnik,spuuuuutnik
'''
s_data = re.sub("spu{2,4}t", "교", data) #sp를 포함하며 u가 2번 이상 4번 이하를 반환
s_data2 = re.sub("spu{2,}t", "교", data) #sp를 포함하며 u가 2번 이상이면 반환
s_data3 = re.sub("spu{,3}t", "교", data) #sp를 포함하며 u가 3번 이하이면 반환
print(s_data)
print(s_data2)
print(s_data3)
sputnik,교nik,교nik,교nik,spuuuuutnik
sputnik,교nik,교nik,교nik,교nik
교nik,교nik,교nik,spuuuutnik,spuuuuutnik
예) ? 는 ? 앞의 문자가 2번 이상 사용되었다면 반환하지 않음.
#정규식 ?을 활용한 매치. ? 가 의미하는 것은 {0,1}이므로 1번만 사용되거나 사용되지 않았을 때를 반환.
data = '''
sptnik,sputnik,spuutnik,spuuutnik,spuuuutnik,spuuuuutnik
'''
s_data = re.sub("spu?t", "교", data)#u가 0번부터 1번 사용된 것만 반환.
print(s_data)
교nik,교nik,spuutnik,spuuutnik,spuuuutnik,spuuuuutnik
정규 표현식을 사용한 문자열 검색
- 정규식으로 컴파일 된 객체를 사용한 문자열 검색. 정규식으로 컴파일 된 객체는 4가지 메서드를 제공한다.
메서드 | 목적 |
match() | 문자열의 처음부터 정규식과 매치되는지 조사 |
search() | 문자열 전체를 검색하여 정규식과 매치되는지 조사 |
findall() | 정규식과 매치되는 모든 문자열(substring)을 리스트로 반환 |
finditer() | 정규식과 매치되는 모든 문자열(substring)을 반복 가능한 객체로 반환 |
예) match()
import re # 정규 표현식 모듈 임포트
data = "sptnik"
data2 = "tniksp"
s_data = re.compile('[sp]+') #정규 표현식을 컴파일 한 객체 s_dats라는 패턴, s나 p로 시작하는 모든 문자열을 의미
#match는 문자열의 처음부터 정규식과 매치되는 지를 조사
m = s_data.match(data) #문자열의 처음이 패턴과 매치됨
print(m)
n = s_data.match(data2) #문자열의 처음이 패턴과 매치되지 않아서 none을 반환
print(n)
<re.Match object; span=(0, 2), match='sp'> # s나 p로 시작되는 인덱스는 첫번째, 두번째 글자야~
None #s나 p로 시작되는 걸 못찾겠어.
예) search()
#search는 문자열 전체를 검색하여 패턴과 매치되는 지 조사
data = "sptnik"
data2 = "tniksp"
s_data = re.compile('[sp]+')
m = s_data.search(data) #문자열 전체를 보니 패턴이랑 매치되는 건 1,2번째 글자네.
print(m)
n = s_data.search(data2) #문자열 전체를 보니 패턴이랑 매치되는 건 5,6번째 글자네.
print(n)
<re.Match object; span=(0, 2), match='sp'>
<re.Match object; span=(4, 6), match='sp'>
예) findall()
#findall
data = "sptnik is big spot!!"
s_data = re.compile('[sp]+')
m = s_data.findall(data) #문자열 전체를 검색해 패턴과 비교하고, 맞는 단어를 리스트로 반환
print(m)
['sp', 's', 'sp']
예) finditer()
#finditer
data = "sptnik is big spot!!"
s_data = re.compile('[sp]+')
m = s_data.finditer(data) #문자열 전체를 검색해 패턴과 비교하고, 맞는 단어를 반복 가능한 객체로 반환
print(m)
for i in m:
print(i)
<callable_iterator object at 0x000001F4544EC520>
<re.Match object; span=(0, 2), match='sp'>
<re.Match object; span=(8, 9), match='s'>
<re.Match object; span=(14, 16), match='sp'>
match() 메서드로 받은 match 객체의 메서드
메서드 | 목적 |
group() | 매치된 문자열을 반환 |
start() | 매치된 문자열의 시작 위치를 반환 |
end() | 매치된 문자열의 끝 위치를 반환 |
span() | 매치된 문자열의 (시작, 끝)에 해당하는 튜플을 반환 |
예)
#match 객체의 메서드
data = "sptnik"
s_data = re.compile('[sp]+')
m = s_data.match(data) #문자열의 처음이 패턴과 매치됨
print(m)
print(m.group())#매치된 문자열을 반환
print(m.start())#매치된 문자열의 시작 위치를 반환
print(m.end())#매치된 문자열의 끝 위치를 반환
print(m.span())#매치된 문자열의 (시작, 끝)에 해당하는 튜플을 반환
<re.Match object; span=(0, 2), match='sp'>
sp
0
2
(0, 2)
예) 위 코드와 같은 코드를 아래와 같이 축약해 표현도 가능
#match 객체의 메서드를 축약형태로 표현
data = "sptnik"
m = re.match('[sp]+',data) #문자열의 처음이 패턴과 매치됨
print(m)
print(m.group())#매치된 문자열을 반환
print(m.start())#매치된 문자열의 시작 위치를 반환
print(m.end())#매치된 문자열의 끝 위치를 반환
print(m.span())#매치된 문자열의 (시작, 끝)에 해당하는 튜플을 반환
정규식의 컴파일 옵션
옵션 | 약어 | 의미 |
DOTALL | S | ' . ' 닷이 줄바꿈 문자를 포함 모든 문자와 매치할 수 있도록 한다. |
IGNORECASE | I | 대소문자 구분없이 매치될 수 있도록 한다. |
MULTILINE | M | 여러 줄과 매치될 수 있도록 한다. (^, $) 메타문자와 함께 사용 |
VERBOSE | X | 복잡한 정규식에 주석이나 줄바꿈을 가능하게 만듬 |
DOTALL, S
- 메타 문자는 줄바꿈 문자를 제외한 모든 문자와 매치되는 규칙 때문에 만약 \n 문자도 매치가 필요할 경우 사용
예)
#DOTALL, S
data = """s\nptnik zunon1979
"""
s_data = re.compile('s.t', re.DOTALL)
m = re.match('s\np', data)
print(m)
<re.Match object; span=(0, 3), match='s\np'>
IGNORECASE, I
- 대소문자 구분 없이 매치 수행할 때 사용
예)
#IGNORECASE, I
data = "sputnik1234, Sputnik1234, SPUTNIK, sputnik, Sputnik"
pattern = re.compile('[a-z]', re.I) #알파벳으로 이루어진 패턴, 대소문자 모두 포함
s_data = pattern.sub('쿄', data)
print(s_data)
쿄쿄쿄쿄쿄쿄쿄1234, 쿄쿄쿄쿄쿄쿄쿄1234, 쿄쿄쿄쿄쿄쿄쿄, 쿄쿄쿄쿄쿄쿄쿄, 쿄쿄쿄쿄쿄쿄쿄
MULTILINE, M
- 메타 문자 ^, $연관된 옵션으로 ^는 문자열의 처음, $는 문자열의 마지막을 의미한다.
- 정규식이 만약 ^sputnik 인 경우 문자열의 처음이 항상 sputnik으로 시작해야 매치가 되고,
정규식이 만약 sputnik$ 인 경우 문자열의 마지막이 항상 sputnik으로 끝나야 매치가 된다.
예)
#MULTILINE, M
data = """
sputnik7565,
sputnik is first satellite,
and my favorite id is sputnik!!
"""
pattern = re.compile("^sputnik")
pattern2 = re.compile("^sputnik", re.M)
print(pattern.findall(data)) #MULTILINE이 적용안되었을 경우 첫줄이 아무 문자열이 없으므로 빈문자로 출력
print(pattern2.findall(data)) #매줄의 첫번째가 sputnik으로 시작되면 찾아서 sputnik을 반환
[]
['sputnik', 'sputnik']
'AI > Python' 카테고리의 다른 글
NLP 학습을 위한 기본 지식 #한국어의 단위 (0) | 2021.10.12 |
---|---|
Python #데이터 전처리 (0) | 2021.09.29 |
Python #파이썬의 대모험 02 (0) | 2021.09.01 |
Python #파이썬의 대모험 01 (2) | 2021.08.31 |
Python #실습 #반복문 활용 #조건문 (0) | 2021.08.31 |