정규식 따라잡기
정규식 (Regular expression)
정규식은 텍스트에서 특정 글자나 단어, 패턴 등을 정확하고 유동적으로 표현하는 식이다. 이는 파이썬과는 관계 없는, 하나의 독립된 언어이다.
정규식: 문자열 비교나 처리를 위한 와일드 카드 표현식!
정규식 Cheat Sheet
기호 | 설명 |
---|---|
^ | 라인 첫번째에서만 |
$ | 라인 마지막에서만 |
. | 아무 문자나 ‘1 개’ (숫자안됨) |
\s | 공백 |
\S | 공백아닌것 |
* | 바로 앞 글자 반복(0개 포함) |
*? | 바로 앞 글자 반복(0개포함) (Non-greedy) |
+ | 바로 앞 글자 반복(1개부터) |
+? | 바로 앞 글자 반복(1개부터) (Non-greedy) |
[AEIOU] | []안에 있는 글자 중 ‘1 개’ |
[\^XYZ] | []안에 없는 글자 중 ‘1 개’ |
[a-z0-9] | range안에 있는 글자 중 ‘1 개’ |
( | 추출대상 시작할 때 |
) | 추출대상 끝날 때 |
예 시
파이썬에서 정규식을 사용하려면, 먼저 정규식 모듈 임포트를 해야 한다. import re
를 사용.
기존 파이썬의 find()
메소드와 비슷하게 사용할 수 있다.
아래와 같은 txt파일이 있다고 해보자.
From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16
Return-Path: <postmaster@collab.sakaiproject.org>
From: stephen.marquard@uct.ac.za
Subject: [sakai] svn commit: r39772
여기서 from:
으로 시작하는 줄을 추출하고 싶다면?
기존의 find()
메소드
hand = open('mbox-short.txt')
# for loop을 txt파일에 대해 실행하면 한 줄씩 들어간다.
for line in hand:
line = line.rstrip() # string 끝부분 공백 제거
# find() 는 결과가 없을 때 -1을 반환함
if line.find('From:') >= 0:
print(line)
re.search()
메소드: True/False로 리턴함.
hand = open('mbox-short.txt')
for line in hand:
line = line.rstrip()
if re.search('From:', line) :
print(line)
특수문자를 사용해 원하는 결과값 추출하기
아래와 같은 텍스트에서
X-Sieve: CMU Sieve 2.3
X-DSPAM-Result: Innocent
X-Plane is behind schedule: two weeks
X-: Very short
-
X부터 :까지 추출하고 싶다?
X.*:
라고 쓰면 됨.X
로 시작하고,.
이 여러 개 (*
)있고 마지막에:
로 끝난다는 뜻. -
X가 반드시 맨 앞에 와야만 한다?
^X.*:
-
중간에 공백이 있으면 안된다?
^X\S+:
. \S는 공백이 아닌 글자를 뜻한다.+
는*
과 얼핏 비슷하지만 최소 1개는 있어야 한다는 뜻이다. 따라서 이 경우에는 ‘X:’ 와 같은 것은 추출되지 않는다.
re.findall()
re.search()와 if를 조합할 필요 없이, 있으면 그 문자열을 바로 출력해 주는 re.findall()을 사용해 보자.
[]중괄호는 range를 사용할 수 이다. 0부터 9 까지 숫자가 1개이상(+
) 있는 경우, A,E,I,O,U 중 하나 이상 있는 경우.
만약 못 찾으면 false가 아닌 빈 list를 반환함에 주의.
>>> import re
>>> x = 'My 2 favorite numbers are 19 and 42'
>>> y = re.findall('[0-9]+',x)
>>> print(y)
['2', '19', '42']
>>> y = re.findall('[AEIOU]+',x)
>>> print
Greedy 정규식.
정규식은 matching이 되면 최대한 길게 결과를 출력한다.
>>> import re
>>> x = 'From: Using the : character'
>>> y = re.findall('^F.+:', x)
>>> print(y)
['From: Using the :']
당연히 그 반대의 경우(옵셔널) 을 ?
를 이용해 사용가능.
>>> import re
>>> x = 'From: Using the : character'
>>> y = re.findall('^F.+?:', x)
>>> print(y)
['From:']
()를 이용한 섬세한 문자열 추출
매칭되는 결과값 중에서도, 일부분만 추출하고 싶을 때.
@
양 옆으로 공백이 아닌 부분을 출력해보자.
>>> import re
>>> x = 'From stephen.marquard@uct.ac.za Sat Jan'
>>> y = re.findall('\S+@\S+', x)
>>> print(y)
['stephen.marquard@uct.ac.za']
이 때, 메일 주소 중에서도 반드시 ‘From’으로 시작하는 줄에 있는 것들만 추출하고자 한다면?
>>> import re
>>> x = 'From stephen.marquard@uct.ac.za Sat Jan'
>>> y = re.findall('^From (\S+@\S+)', x)
>>> print(y)
['stephen.marquard@uct.ac.za']
응용편
메일 주소 중 도메인만 출력해 보자.
>>> import re
>>> x = 'From stephen.marquard@uct.ac.za Sat Jan'
>>> y = re.findall('^From @([^ ]*)', x)
>>> print(y)
['uct.ac.za']
해설
기호 | 뜻 |
---|---|
^From | 시작은 From이어야 함 (IF문 같은 것) |
’ ‘ | From과 @ 사이에 공백 있어야 하고 |
.* | 아무 글자든지간에 (.) 0개이상 있어야(* ) |
@ | @로 시작해야하고 |
( ) | 여기만 출력할거야 |
[ ] | 이 안에 있는 1글짜씩인 놈들인데 |
^ | 공백이 아닌 거 (원래 ^는 맨 첫줄인데 뭐 NOT의 의미도 있나봄) |
* | 조건을 만족하는 한 끝까지 가자 (Greedy) |
이런 느낌이다.
이스케잎 문자
만약 string중에서 $ 로 시작하는 부분을 추출하려면 어떻게 해야 하나? $는 라인 마지막에서만 찾으라는 뜻인데. 이럴 떄는 \ (백슬래쉬)를 사용하면 된다.
>>> import re
>>> x = 'We just received $10.00 for cookies.'
>>> y = re.findall('\$[0-9.]+',x)
>>> print(y)
['$10.00']
댓글남기기