본문 바로가기
카테고리 없음

[PYTHON] 정규표현식 : re library

by alasdkfm 2023. 9. 18.

정규식

패턴 의미 활용
. 줄바꿈 문자를 제외한 1글자를 의미 .{3} : 문자3개 
ex. 0x0 , F11
^ 문자열의 시작을 의미. 또는 not의 의미. ^abc : abc로 시작되어야 함 
[^문자열] : not의 의미/ 문자열이 아닌것들
$ 문자열의 끝을 의미 xyz$ : xyz로 종료되어야 함 
[] 문자의 집합 [xyz] : x또는 y또는 z라는 문자와 매칭.
ex. [Pp]ython  : Python, python 둘다가능

[x-z] : x~z 범위.

[^a] : a를 제외한 모든 문자를 의미.
| 두 패턴 중 하나여야함 (or) a|b : a 또는 b문자를 의미
() 어떤 정규식을 하나의 그룹으로 묶어줌 ([a-c])([x-z]) : a, b, c와 매칭될 수 있는 그룹 1개와 x, y, z와 매칭될 수 있는 그룹을 의미.
ex : ax, az, by... 

만약 괄호라는 문자 자체를 매칭하고싶으면 \(, \) 등으로 백슬래쉬를 이용한 escape를 해줘야 함.
* 0회 이상 반복되는 패턴 a* : a가 0번 이상 반복되는 패턴
/d* : 숫자가 0회이상
+ 1회 이상 반복되는 패턴 a+ : a가 1번 이상 반복되는 패턴
/d+ : 숫자가 1회이상
? 어떤 문자가 0회 또는 1회 반복되는 패턴을 나타냄 a? : a가 0번 또는 1번 존재
/d? : 숫자가 0회 또는 1회  
{n} 문자가 n회 반복되는 패턴을 나타냄 whi{3}te : whiiite를 의미
/d{3} : 숫자 3개 
{m,n} 문자가 m회 ~ n회 반복되는 패턴을 나타냄 wh{2, 4}ite : whhite, whhhite, whhhite를 의미
/d{2,4} ; 숫자 2~4개 
{m,} 자가 m회부터 무한대까지 반복되는 패턴을 나타냄 wh{2,}ite : whhite, whhhite, whhhhite, whhhhite, .... 등을 나타냄
\w 모든 문자 의미 : [a-zA-Z0-9_] \w\w\w : 문자 3개 의미 
ex. abc , Abc ,, 
\W 숫자, underscore(_)를 포함하는 모든 언어의 표현가능한 문자를 제외한 나머지 문자
 = [^a-zA-Z0-9_]
 
\d 0~9의 숫자를 포함한 모든 숫자
= [0-9]와 동일
/d* : 숫자가 0회이상
/d? : 숫자가 0회 또는 1회  
/d{3} : 숫자 3개 

/d{2,4} ; 숫자 2~4개 ,,,
\D 0~9의 숫자를 제외한 모든 숫자
= [^0-9]와 동일
 
\s 화이트 스페이스 
: [\t\n\r\f\v]를 포함하는 공백문자

\t = 탭  \n = 줄바꿈  \r = 캐리지 리턴  \f = 폼피드\v = 수직 탭
\s\s : 공백문자 두개 
\S [\t\n\r\f\v]를 제외한 공백문자
= [^\t\n\r\f\v]와 동일
 
\b 단어의 시작과 끝에 존재하는 공백  
\B 단어의 시작과 끝이 아닌 곳에 존재하는 공백  
\[숫자] 표시된 숫자만큼 일치하는 문자열을 의미  

 

re.sub : 조건 만족 문자열 치환 

형태

import re 
re.sub(pattern, replace , text , max_sub_num)
# text중 패턴에 해당되는 부분을 replace 한다. 
# 만약 최대교체수(max_sub_num)를 지정하면, 해당 숫자 이상으로는 교체x

 

활용1 :

import re


print(re.sub('a', 'z', 'ab'))
print(re.sub('a', 'zxc', 'ab'))
print(re.sub('a', 'z', 'aaaab'))
print(re.sub('a', 'z', 'aaaab', 1))

--Result
zb
zxcb
zzzzb
zaaab

활용2 : [프로그래머스]신규 아이디 추천

import re
def solution(new_id):
    st = new_id
    
    #1단계 : 소문자로 변경 
    st = st.lower()		
    
    #2단계 : 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자를 제거
    st = re.sub('[^a-z0-9\-_.]', '', st)	
    
    #3단계 : 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환
    st = re.sub('\.+', '.', st)			# '.'패턴이 1개 이상(+)이라면, '.' 으로 치환
    
    #4단계 : 마침표(.)가 처음이(^)나 끝($)에 위치한다면 제거
    st = re.sub('^[.]|[.]$', '', st)		
    
    #5&6단계 : 빈 문자열이라면, new_id에 "a"를 대입 & 길이는 15자까지
    st = 'a' if len(st) == 0 else st[:15]		
    
    #6단계 : 마침표(.)가 처음이나 끝에 위치한다면 제거
    st = re.sub('^[.]|[.]$', '', st)				
   
    #7단계 : 길이가 2자 이하라면, new_id의 마지막 문자를 new_id의 길이가 3이 될 때까지 반복 
    st = st if len(st) > 2 else st + "".join([st[-1] for i in range(3-len(st))])
    
    
    return st

 

FLAG 종류 

- re.IGNORECASE : 대소문자 구별X 

print(re.match('[a-zA-Z]+', 'abcABC'))
# <re.Match object; span=(0, 6), match='abcABC'>

print(re.match('[a-z]+', 'abcABC', flags=re.IGNORECASE))
# <re.Match object; span=(0, 6), match='abcABC'>

print(re.match('[A-Z]+', 'abcABC', flags=re.IGNORECASE))
# <re.Match object; span=(0, 6), match='abcABC'>

 

- re.MULTILINE : text가 여러줄인 경우, 각 행의 선두/후미를 매칭할 수 있다  (^,$와 함께 사용)

단축형으로 re.M 도 가능 

s = '''aaa-xxx
bbb-yyy
ccc-zzz
'''

-- 선두 
print(re.findall('[a-z]+', s))
# ['aaa', 'xxx', 'bbb', 'yyy', 'ccc', 'zzz']

print(re.findall('^[a-z]+', s))  # 첫번째 행의 선두만 매칭 
# ['aaa']

print(re.findall('^[a-z]+', s, flags=re.MULTILINE)) # 각 행의 선두 매칭 
# ['aaa', 'bbb', 'ccc']


-- 후미 
print( re.findall('[a-z]+$', s))
# ['zzz']

print( re.findall('[a-z]+$', s, flags=re.MULTILINE))
# ['xxx', 'yyy', 'zzz']

 

re.match : 문자열의 처음부터 조건에 만족하면 객체반환 

형태

re.match(pattern, text,flag)
#문자열 처음부터 패턴이 일치하는지 확인

활용

import re

print(re.match('a', 'ab')) #1 
print(re.match('a', 'ba')) #2

-- Result
<re.Match object; span=(0, 1), match='a'> #1 a로 시작o
None                                      #2 a로 시작x -> 매칭결과없음

 

re.search : 조건 만족하는 첫번째 문자 객체 반환

re.match와 유사하지만, 패턴만 일치한다면 처음부터 일치하지 않아도 괜찮음. 

형태

import re
re.search(pattern, text)
# text 중 pattern에 해당하는 첫번째 문자열을 반환한다.

활용

import re

text = 'This is example word 12345'

search_result = re.search(r'e[a-z]{5}e', str_test) #1 
print(search_result) #2
print(search_result.span()) #3
print(search_result.group()) #4


-- Result
<re.Match object; span=(8, 15), match='example'>  #2 결과
(8, 15)  #3 결과
example  #4 결과

1. e로 시작하고 e로 끝나며 그 사이에 알파벳 소문자 5개가 있는 패턴을 text에서 찾기.

2. 결과물은 search 객체로 반환.

3. search.span():  (시작지점, 끝지점), 0부터 시작.

4. search.group()은 찾은 텍스트 반환. 예시에서는 찾은 단어가 example이므로, example를 반환함. 

 

import re

text = 'This is example word 12345'

search_case_1 = re.search(r'[a-z]{3}', text) #1
print(search_case_1.group())

search_case_2 = re.search(r'[0-9]{3}', text) #2
print(search_case_2.group())

search_case_3 = re.search(r'[a-z]{2}\s[a-z]{7}', text)  #3
print(search_case_3.group())


-- Result
his #1 
123 #2
is example #3

1. [a-z]{3} : 소문자 알파벳 연속 3개 나오는 패턴  → This is example word 12345

2. [0-9]{3} : 숫자가 연속해서 3개 나오는 패턴  This is example word 12345

3. [a-z]{2}\s[a-z]{7} : 소문자 2개 + 띄어쓰기 + 소문자 7개  This is example word 12345

 

re.fullmatch: 문자열 전체가 조건을 만족하면 객체 반환

형태 

import re
re.fullmatch(patternn,text,flag)

활용

text1 = 'abc@xxx.com'
text2 = '!!!aaa@xxx.com!!!'

print(re.fullmatch(r'[a-z]+@[a-z]+\.com', text1))
print(re.fullmatch(r'[a-z]+@[a-z]+\.com', text2))


--Result
<re.Match object; span=(0, 11), match='abc@xxx.com'>
None

 

re.findall : 조건 만족 모든 문자열 리스트 형태로 반환 

형태

import re
re.findall(pattern, text,flag)
# text 중 pattern에 해당하는 부분을 모두 반환한다.

활용

import re

text = 'I_LOVE_U_SO_MUCH_MYLUV_LOVE'

print( re.findall(r'LOVE', str_text)) #1
print( re.findall(r'L[A-Z]{2}', text)) #2

-- Result
['LOVE','LOVE'] #1 

['LOV','LUV','LOV'] #2

정규표현식 의미 

1. 'LOVE' 찾기 

2. L로 시작하며, A부터 Z까지의 대문자 알파벳( [A-Z] ) 2개( {2} )가 뒤이어 나오는 문자열을 탐색하라는 의미입니다.

따라서 'I_LOVE_YOU_SO_MUCH_MYLUV'에서 LOV와 LUV가 반환된다 

 

TEXT = 'abc123def56ghi'
re.findall('\d+', TEXT)

-- Result
['123', '56']


print(re.findall('a', 'a'))
print(re.findall('a', 'aba'))
print(re.findall('a', 'baa'))

print(re.findall('aaa', 'aaaaa'))
print(re.findall('aaa', 'aaaaaa'))
print(re.findall('\d', '숫자123이 이렇게56 있다8'))
print(re.findall('\d+', '숫자123이 이렇게56 있다8'))

-- Result
['a']
['a', 'a']
['a', 'a']

['aaa']
['aaa', 'aaa']
['1', '2', '3', '5', '6', '8']
['123', '56', '8']

 

re.split : 조건에 따라 문자열 나누기 

형태

import re
re.split(pattern, text, max_split_num ) 

# 문자열에서 패턴이 맞으면 이를 기점으로 리스트로 분할. 
# 만약 최대 split수(max_split_num)을 지정하면, 그 이상으로는 나눠지지 x

활용 

import re

print(re.split('a', 'abaabca'))
print(re.split('a', 'abaabca', 2))

--Result
['', 'b', '', 'bc', '']
['', 'b', 'abca']

 

re.compile : 정규식 객체 리턴 

한번 만든 패턴 객체를 여러번 사용할 때 사용 

 

형태

import re

re.compile(pattern)

활용

target_string = "123python456"

## 예시1 
pattern = re.compile('[a-z]+')
result = pattern.match(target_string)

# 위와 동일. 축약형
result = re.match("[a-z]+",target_string)


## 에시2 
pattern = re.compile(r'\d{3}')
result = pattern.findall(target_string)  #['123','456']

# 위와 동일. 축약형
result = re.findall(r'\d{3}')           # ['123','456']

 

 

참고 : 

달나라 노트

한줄한줄 코디일기