코학다식

[파이썬(Python)] 정규 표현식 알아보기(1) 본문

Programming/Python

[파이썬(Python)] 정규 표현식 알아보기(1)

copeng 2019. 8. 27. 19:22

파이썬 정규 표현식 알아보기 (1)

 

 

정규 표현식이란?


 

정규 표현식(regular expression)이란 특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어이다.

 

정규 표현식의 기초는 메타 문자!


 

메타 문자(meta characters)는 원래 그 문자가 가진 뜻이 아닌 특별한 용도로 사용하는 문자를 말한다. 정규 표현식에 사용되는 메타 문자로는 . ^ & * + ? { } [ ] \ / ( ) _가 있다.

 

1. 문자 클래스 [ ]


 

  • [ ] 사이에는 어떤 문자든 들어갈 수 있다.
  • [abc]라면 "a, b, c 중 한 개의 문자와 매치"를 의미한다.
  • [ ]의 두 문자 사이에 하이픈(-)을 사용하면 두 문자 사이의 범위를 의미한다. (ex. [a-zA-Z]는 알파벳 모두, [0-9]는 숫자)
  • 문자 클래스 안에 ^ 를 사용하면 반대(not)를 의미한다.
  • 다음은 자주 사용하는 문자 클래스이다.
표기 의미
\d 숫자와 매치, [0-9]
\D 숫자가 아닌 것과 매치
\s whitespace 문자와 매치, [ \t\n\r\f\v] - 맨 앞 빈칸은 공백 의미
\S whitespace 문자가 아닌 것과 매치
\w 문자+숫자와 매치, [a-zA-Z0-9_]
\W 문자+숫자가 아닌 문자와 매치

 

  1. Dot(.)

 

  • 줄바꿈 문자인 \n 을 제외한 모든 문자와 매치됨을 의미한다.
  • 가령, a.b"a + 모든 문자 + b"를 의미한다.
  • 주의할 점은, 문자 클래스 안에 dot(.)이 사용된다면 이는 "모든 문자"를 의미하는게 아니라 문자 그대로의 .을 의미한다. 따라서 a[.]b라는 정규식은 "a.b"라는 문자열과 매치된다.

 

  1. 반복(*, +, { })

 

  • *의 바로 앞에 있는 문자가 0부터 무한대로 반복될 수 있음을 의미한다. (실제로는 메모리 제한으로 2억 개 정도만 가능하다.)
  • 가령, ca*t라는 표현식은 * 앞의 문자 a가 0부터 무한대로 반복될 수 있다는 의미이다. 즉, ct라는 문자열과도 매치가 가능하다.
  • 반복을 나타내는 또 다른 메타 문자로 +가 있는데, 이는 최소 1번 이상 반복될 때 사용한다. *가 반복 횟수 0부터라면 +는 반복 횟수 1번 부터인 것이다.
  • { } 메타 문자를 사용하면 반복 횟수를 고정할 수 있다. {m, n} 정규식을 사용하면 반복 횟수 m부터 n까지 매치할 수 있다. m 또는 n을 생략할 수도 있는데, {3,}은 횟수가 3 이상인 경우를 의미하고 {,3}은 횟수가 3 이하인 경우를 의미한다.

 

정규식 Match 가능한 문자열 설명
ca{2}t caat "a"가 두 번 반복되어 매치, 두 번 반복이 아니라면 매치 불가
ca{2, 5}t caaaaat "a"가 다섯 번 반복되어 매치

 

  • 반복과 비슷한 개념인 ? 메타 문자는 {0, 1}을 의미한다. 즉 바로 앞의 문자가 있어도 되고 없어도 되는 것이다.

 

  1. 파이썬에서 정규 표현식을 지원하는 re 모듈

 

  • 파이썬은 정규 표현식을 지원하기 위해 re(regulra expression의 약어) 모듈을 제공한다. 파이썬을 설치할 때 자동으로 설치된다.
>>> import re
>>> p = re.compile('ab*')

 

  • re.compile을 사용하여 정규 표현식을 컴파일한다. 그 결과를 알려 주는 객체 p(컴파일된 패턴 객체)를 사용하여 그 이후의 작업을 수행할 것이다.

패턴이란 정규식을 컴파일한 결과이다.

 

  1. 정규식을 이용한 문자열 검색

 

  • 컴파일된 패턴 객체는 다음과 같은 네 가지 메서드를 제공한다.

 

Method 목적
match() 문자열의 처음부터 정규식과 매치되는지 조사한다.
search() 문자열 전체를 검색하여 정규식과 매치되는지 조사한다.
findall() 정규식과 매치되는 모든 문자열(substring)을 리스트로 돌려준다.
finditer() 정규식과 매치되는 모든 문자열(substring)을 반복 가능한 객체로 돌려준다.

 

  • march, search는 정규식과 매치될 때는 match 객체를 돌려주고, 매치되지 않을 때는 None을 돌려준다.

match 객체란 정규식의 검색 결과로 돌려주는 객체이다.

 

예시 코드를 통해 match와 search의 차이를 알아보자.

>>> import re
>>> p = re.compile('[a-z]+')
>>> m = p.match("python")
>>> print(m)
<re.Match object; span=(0, 6), match='python'>
>>> m = p.match("3 python")
>>> print(m)
None

위의 예시에서 "python" 문자열은 [a-z]+ 정규식에 부합되므로 match 객체를 돌려주지만, "3 python"은 처음에 나오는 문자 3이 정규식에 부합되지 않으므로 None을 돌려준다. match의 결과로 match 객체 또는 None을 돌려주기 때문에 파이썬 정규식 프로그램은 match 객체 유무에 따라 다음 작업을 수행하는 흐름으로 작성한다.

같은 패턴 객체 p를 가지고 search 메서드를 수행해 보자.

>>> m = p.search("python")
>>> print(m)
<re.Match object; span=(0, 6), match='python'>
>>> m = p.search("3 python")
>>> print(m)
<re.Match object; span=(2, 8), match='python'>

"python" 문자열에서는 동일한 결과가 나온다. 그런데 "3 python"에서도 match 객체를 돌려준다. 결과가 match와 다른 이유는 "3 python" 문자열의 첫 번째 문자는 "3"이지만 search는 문자열의 처음부터 검색하는 것이 아니라 문자열 전체를 검색하기 때문에 "3 " 이후의 "python" 문자열과 매치된다.

즉, match 메서드와 search 메서드의 차이는 문자열의 처음부터 검색할지의 여부에 따라 달라지는 것이다. 문자열 전체를 검색하고 싶다면 search 메서드를 사용해야 한다.

 

패턴 객체 p를 가지고 이번에는 findall 메서드와 finditer 메서드를 수행해 보자.

>>> result = p.findall("life is too short")
>>> print(result)
['life', 'is', 'too', 'short']

findall 메서드는 문자열의 'life', 'is', 'too', 'short' 단어를 각각 [a-z]+ 정규식과 매치해서 리스트로 돌려준다.

finditer를 수행하면 어떨까?

>>> result = p.finditer("life is too short")
>>> print(result)
<callable_iterator object at 0x0000025C7D8A7748>
>>> for r in result: print(r)
...
<re.Match object; span=(0, 4), match='life'>
<re.Match object; span=(5, 7), match='is'>
<re.Match object; span=(8, 11), match='too'>
<re.Match object; span=(12, 17), match='short'>

위와 같이 finditer는 매치 결과로 반복 가능한 객체(iterator object)를 돌려준다. 반복 가능한 객체가 포함하는 각각의 요소는 match 객체이다.

Comments