본문 바로가기

AI/Python

Python #정규식 #정규 표현식

정규 표현식(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']

반응형