본 포스팅은 충남대 이종률 교수님의 강의자료를 바탕으로 작성한 글입니다.

 

정규표현식은 어떤 문장에서 특정한 형태의 문자열을 뽑고 싶을 때 사용하는 것이다.

여러 방식이 있으니, 추출하려는 문자열의 특징을 잘 파악해서 사용해야 한다.

 

[표 정리]

/ /Re pattern/
[abcd] 대괄호 안의 문자들 중 하나
+ + 앞의 문자를 하나 이상
g Globally match
^ ^ 뒤의 문자로 시작되는 문자열
$ $ 앞의 문자로 끝나는 문자열
? ? 앞의 문자가 하나 또는 없음
* * 앞의 문자가 없거나 그 이상
a|b a 또는 b
() ()안의 문자들을 그룹으로 처리
()() 괄호 그룹의 집합
. 어떤 문자든 하나
\s 공백
\S 공백 아닌 문자
[^abcd] abcd가 아닌
[a-z0-9가-힣] 저 범위의 문자들

 

 

[실습]

이런 다양한 정규표현식을 사용하려면, re라는 라이브러리를 import해야하고,

re.search()와 re.findall()을 사용할 수 있다.

search() : 매칭에 성공한 첫 번째 문자열만 반환.

findall() : 매칭에 성공한 모든 문자열 반환.

 

if line.find('abc:')>=0:
if re.search('abc:', line):
if line.startswith('abc:'):
if re.search('^abc:', line):

 

re.searchTrueFalse값을 반환한다.

re.findall은 찾은 모든 문자열들의 위치를 반환한다.

 

근데 여기서 찾을 때, 이 반복 문자들(*, +)는 가~장 긴 문자열과 매치되기 위해 양방향에서 바깥쪽으로 푸시한다.

예를 들어, 

x = 'From: Using the : character'
y = re.findall('^F.+:', x)
print(y)
['From: Using the :']

이렇게, From:이 아니라 From: Using the :가 찾아진다는 점!

 

그치만, +, *와 함께 ?를 쓰게 된다면 얘기가 달라진다.

x = 'From: Using the : character'
y = re.findall('^F.?+:', x)
print(y)
['From:']

이렇게 greedy가 아닌 반환값을 찾게 된다.

 

그리고.. 이 괄호가 조금 특별한데,

x = From dabin.cnu@naver.com Sat Jan 5 09:00:00
y = re.findall('\S+@\S+', x)
print(y)
>> ['dabin.cnu@naver.com']

y = re.findall('^From (\S+@\S+)', x)
print(y)
>> [dabin.cnu@naver.com']

요렇게, 두 번째 코드에서 findall 시행시 From dabin.cnu@naver.com이 매칭은 되지만, y라는 변수에 추출되는 문자열은 dabin.cnu@naver.com이라는 괄호 안의 정규표현식에 해당하는 값이다.

 

이건 왜 쓰냐..? 라 한다면, 

내가 여러 편지를 받았는데, 다들 From 00 이렇게 썼다.

근데 내가 원하는 건 From 00이 아니라 저 이름만 추출하기 원하는 것이다.

그럼 저렇게 From 까지 매칭을 우선 해놓고, 내가 필요한 변수에 저장할 땐 괄호 안의 내용만 저장하면 되는 것!

ex) re.findall('@([^ ]*)', x) 라고 되면, x가 이메일 주소라고 할 때, 도메인 즉 naver.com이나 daum.net같은 것만 추출되는 것임!

 

그리고 또 예시를 들자면, 어떤 데이터 내에서도 이렇게 사용할 수 있다.

만약에 구글폼으로 학과 전원의 키를 조사했다. 근데 이 중에 최댓값을 찾고 싶다면?

hand = open('height.txt')
numlist = list()
for line in hand:
	line = line.rstrip()
    stuff = re.findall('^your height : ([0-9.]+)', line) #키는 소숫점값으로 쓸 수도 있으니 0-9 또는 .을 하나 이상!
    if len(stuff) != 1:
    	continue
    num = float(stuff[0])
    numlist.append(num)
print('Max height :', max(numlist))

이렇게 하면 된단 말씀!

 

그리고, 만약 위에 표에 있던 특수기호들을 저 의미가 아니라 진짜 찾고 싶다면?

\$ 처럼 앞에 역슬래시를 붙이면 된당.