본문 바로가기
Python

파이썬 정규식 02

by eloyb 2024. 12. 21.
반응형

이전 포스팅에 이어서 정규식에 대한 내용을 심화 학습해 보기로 하겠습니다. Greedy vs NonGreedy

Greedy, NonGreedy 라는 부터가 어려운데 Greedy 탐욕스러운 수집가, NonGreedy 탐욕적이지 않고 소박한 수 집가 정도로 생각하시는 게 좋습니다. Greedy를 사용하는 연산자는 별표(*)와 플러스(+)가 있고, NonGreedy를 사용하 는 연산자는 물음표가 있습니다. Greedy 방식으로 자료를 수집하게 되면 탐욕적이기 때문에 최대한 반복해서 자료를 수 집하게 되고, NonGreedy 방식으로 자료를 수집하게 되면 최소 반복을 통해서 자료를 수집하게 됩니다.

>>>import re >>> char = re.compile(r'(0){4,8}') # Greedy 방식의 반복 수집 >>> i = char.search('000000') >>> i.group() '000000' >>> char = re.compile(r'(0){4,8}?') # NonGreedy 방식의 반복 수집 >>> i = char.search('000000') >>> i.group() '0000'

위에서 i = char.search('000000') 에서 0 최대한 6번까지 반복해서 수집할 있도록 했는데 물음표를 사용하지 않으 면 최대한 반복 수집을 하기 때문에 000000 이 출력됩니다. 하지만 물음표(?)를 사용하게 되면 똑같이 영을 최대한 6번 까지 반복해서 수집하도록 했지만 NonGreedy 방식으로 자료를 수집하기 때문에 최소한 반복 수집을 하게 되는 0000 으 로 출력이 되게 됩니다.

 

findall() 메서드

정규식 객체에는 search() 메서드 외에 findall() 메서드가 있습니다. search() 메서드는 검색된 문자열에서 첫번째로 일치 하는 텍스트의 Match() 객체를 반환하지만, findall() 메서드는 검색된 문자열에서 일치하는 모든 문자열을 반환합니다.

>>> import re >>> char = re.compile(r'\d\d\d-\d\d\d\d-\d\d\d\d') >>> char.findall('phone1: 010-1111-2222 phone2: 010-2222-3333') ['010-1111-2222', '010-2222-3333'] >>> char =

re.compile(r'(\d\d\d)-(\d\d\d\d)-(\d\d\d\d)') >>> char.findall('phone1: 010-1111-2222 phone2: 010-2222-3333') [('010', '1111', '2222'), ('010', '2222', '3333')] >>>

특별한 문자 클래스 만들기

문자 클래스를 만들 경우 (\w, \s, \d) 등은 너무 광범위하기 때문에 내가 필요한 문자 클래스만을 정의해야 때가 습니다.

이럴 경우 대괄호 [] 를 이용하여 사용자 고유의 문자 클래스를 정의할 수 있습니다. 예를 들어 문자 클래스 [aeiouAEIOU] 모든 대문자와 소문자의 모음과 일치하게 됩니다. 그리고 하이픈을 사용하여 문자 또는 숫자의 범위를 지정할 수 있습니다. ) [a-zA-Z0-9]

고유의 문자 클래스를 정의해서 사용할때는 일반 정규식의 적용을 받지 않습니다. 예를 들어 [0-9\.] 처럼 문자 클래스를

 

정의하지 않고 [0-9.] 같이 정의해서 사용하면 됩니다. 또한 고유의 문자 클래스를 정의해서 사용할때 ^ 기호는 반대의 의미를 갖습니다. 예를 들어 [^aeiouAEIOU] 는 모든 모음을 제외한 문자를 정의하게 됩니다.

>>> import re >>> char = re.compile(r'[aeiouAEIOU]') >>> char.findall('Making My Own Character Class.') ['a', 'i', 'O', 'a', 'a', 'e', 'a'] >>> char = re.compile(r'[^aeiouAEIOU]') >>> char.findall('Making My Own Character Class.') ['M', 'k', 'n', 'g', ' ', 'M', 'y', ' ', 'w', 'n', ' ', 'C', 'h', 'r', 'c', 't', 'r', ' ', 'C', 'l', 's', 's', '.'] >>>

캐럿(^)과 달러($) 기호 문자

정규식의 시작 부분에 캐럿(^) 기호를 사용하면 검색된 텍스트의 시작 부분에서 일치해야 함을 나타냅니다. 대괄호[] 의 문자 클래스 안에서 사용되는 캐럿과 혼동하지 마시기 바랍니다. 대괄호 안의 캐럿은 반대의 의미를 가지게 됩니다. 정규 식의 끝에 달러($) 기호를 사용하면 문자열이 이 정규식 패턴으로 끝나야 함을 나타냅니다.

>>> import re >>> char = re.compile(r'^Microsoft') >>> char.search('Microsoft Visual Studio') <re.Match object; span=(0, 9), match='Microsoft'> >>> >>> endNumber = re.compile(r'\d$') # \d 는 숫자 0-9를 의미하 고 $ 는 마지막이 이 패턴으로 끝나야 함을 의미 >>> endNumber.search('마지막에 숫자임 123') <re.Match object; span=(11, 12), match='3'> >>> startEndNum = re.compile(r'^\d+$') # 하나 이상의 숫자로 시작하고 끝나는 문자 열을 의미 >>> startEndNum.search('12345') <re.Match object; span=(0, 5), match='12345'> >>> startEndNum.search('123abc456') == None True >>>

와일드카드(.) 문자

(dot) 문자는 와일드카드라고 하며 행 바꿈을 제외한 모든 문자에 대응합니다. 점 문자는 단 하나의 문자와 매칭됩니다.

>>> char = re.compile(r'..ly') >>> char.findall('soly, poly, ugly, aimly, bamly') ['soly', 'poly', 'ugly', 'imly', 'amly'] >>>

와일드카드(.), 별표(*), 물음표(?)를 같이 사용

예를 들어 이름: 직업: 등으로 분류되어 있는 자료가 있을 경우 이름과 직업 뒤에 오는 모든 문자에 대응하려고 할때는 (.)과 별표(*)를 같이 사용해서 일치하는 데이터를 찾을 수 있습니다. 점 문자는 단일 문자를 의미하고 별표는 앞에 오는 문자중에서 0 개 이상을 의미하기 때문입니다. 점과별표를 같이 사용하는 것은 greedy mode 가 됩니다. 만약 nonegreedy mode를 사용하려면 점, 별표, 물음표(.*?) 를 사용하면 됩니다.

>>> import re >>> char = re.compile(r'이름: (.*) 직업: (.*)') >>> i = char.search('이름: 이시영 직업: 배우') >>> i.group(1) '이시영' >>> i.group(2) '배우' >>> >>> char = re.compile(r'<.*?>') >>> i = char.search('<이름> 이시영

>') >>> i.group() '<이름>' >>> char = re.compile(r'<.*>') >>> i = char.search('<이름> 이시영>') >>> i.group() '<이 름> 이시영>' >>>

DOTALL 사용

점과별표(.*) 이용하면 바꿈을 제외한 모든 것에 일치시킨다는 것을 이미 배웠습니다. 그렇다면 바꿈을 포함시켜 서 모든 것에 일치시키려면 어떻게 해야 할까요? 이 경우엔 re.DOTALL을 사용하면 됩니다.

>>> import re >>> char = re.compile('.*', re.DOTALL) >>> char.search('Microsoft Visual Studio \nMicrosoft Office \nMicrosoft Windows').group() 'Microsoft Visual Studio \nMicrosoft Office \nMicrosoft Windows'

>>> 

re.I 사용

 

정규식은 일반적으로 대소문자를 구분해서 데이터를 찾습니다. 그런데 가끔 대소문자를 구분하지 않고 데이터를 찾아야 할때가 있습니다. 그럴 경우 re.I 를 사용하여 대소문자를 구분하지 않는 정규식을 사용할 수 있습니다.

>>> import re >>> char = re.compile(r'microsoft', re.I) >>> char.search('Microsoft').group() 'Microsoft' >>> char.search('MICROSOFT').group() 'MICROSOFT' >>>

sub() 메서드 사용

sub() 메서드를 사용하면 정규식을 이용해서 텍스트를 찾고 다른 문자열로 바꿀 있습니다. sub() 메서드는 두개의 인수 가 있는데 첫번째 인수는 바꿀 문자열, 두번째 인수는 정규식의 문자열입니다.

>>> import re >>> char = re.compile(r'Samsung \w+') # \w 모든 문자 + 1 이상의 문자를 의미 >>> char.sub('LG', 'Samsung Smart Phone') # 결국 Samsung Smart LG로 바꾸게 된다. 'LG Phone' >>>

sub() 메서드를 배웠으니 이제 적당한 예제를 한번 만들어 보도록 하겠습니다. 지금은 보통 웹사이트에서 회원 가입시 주 민번호를 요구하지 않지만 아직까지도 은행이나 증권사이트에 들어가서 첫 회원 가입을 하려면 주민번호를 요구합니다. 이외에도 온라인 고지서에서도 주민번호를 요구하기도 합니다. 이 경우 주민번호를 보여줄때 처음 6자리만 보여 주고 뒤 의 7자리는 감추는 경우가 많은데 이런 처리를 정규식을 이용해서 처리해 보도록 하겠습니다. 정규식을 사용하지 않고 처 리하는 방법도 있긴 하지만 정규식을 이용해서 처리하는 것보다 상당히 많은 양의 코드가 필요하다는 것은 굳이 설명드리 진 않도록 하겠습니다.

>>> import re >>> jumin ='801010-1245222' >>> i = re.compile(r'(\d{6})-(\d{7})') >>> print(i.sub('\g<1>-

*******', jumin)) 801010-******* >>>

print 문에서 g<1> 첫번째 그룹을 묶어주는 역할을 합니다. 그룹은 괄호를 이용해서 2개의 그룹으로 나뉘어져 있습니 .

위와 같이 정규식을 이용하면 몇줄의 코드만으로 간단하게(?) 주민번호의 일부를 숨길 수 있습니다.

'Python' 카테고리의 다른 글

파이썬 파일 읽기와 쓰기  (2) 2024.12.26
파이썬 메일주소 추출하기  (2) 2024.12.26
파이썬 정규식 01  (2) 2024.12.21
파이썬 문자열 다루기  (4) 2024.12.21
파이썬(Python) 딕셔너리  (3) 2024.11.30