본문 바로가기
Tech Stack/Python

정규 표현식

by jaeaemin 2021. 8. 13.

복잡한 문자열을 처리할 때 사용하는 기법으로 파이썬 뿐만 아니라 다른 모든 곳에서 자주 사용된다.

메타 문자

메타 문자란 원래 그 문자가 가진 뜻이 아닌 특별한 용도로 사용하는 문자를 말한다. 

 

 

문자 클래스 [ ]

 

 

문자 클래스로 만들어진 정규식은 "[ ] 사이의 문자들과 매치" 라는 의미를 갖는다. 이 때 [] 사이에는 어떤 문자도 들어갈 수 없다.

이 때 하이폰(-)을 사용하면 두 문자 사이의 범위를 의미한다. (^)은 부정으로 반대를 의미한다.

 

(1) a
(2) bee
(3) dot

-1-     [ a b c ] : (1)은 정규식과 일치하는 'a'가 있으므로 매치 , (2)도 'b'로 인해 매치 (3) 은 포함하는 문자가 없어 매치 X

-2-    [ a-zA-z ] : 알파벳 모두 해당하므로 (1) (2) (3) 모두 매치

-3-    [^0-9] : 숫자가 아닌 모든 표현식이므로 문자인 (1) - (3) 모두 매치

 

[ 자주 사용하는 문자 클래스 ] 

[0-9] 또는 [a-zA-Z] 등은 무척 자주 사용하는 정규 표현식이다.
자주 사용하는 정규식은 별도의 표기법으로 표현할 수 있다. 

  • \d - 숫자와 매치, [0-9]와 동일한 표현식이다.
  • \D - 숫자가 아닌 것과 매치, [^0-9]와 동일한 표현식이다.
  • \s - whitespace 문자와 매치, [ \t\n\r\f\v]와 동일한 표현식이다. 맨 앞의 빈 칸은 공백문자(space)를 의미한다.
  • \S - whitespace 문자가 아닌 것과 매치, [^ \t\n\r\f\v]와 동일한 표현식이다.
  • \w - 문자+숫자(alphanumeric)와 매치, [a-zA-Z0-9_]와 동일한 표현식이다.
  • \W - 문자+숫자(alphanumeric)가 아닌 문자와 매치, [^a-zA-Z0-9_]와 동일한 표현식이다.
대문자는 반대를 의미한다.

 

 

DOT (.)

 

줄바꿈 문자인 \n을 제외한 모든 문자와 매치된다. ( re.DOTALL 옵션시 \n 문자와도 매치될 수 있다. )

Dot을 사용한 정규식 a.b" a + 모든문자 + b " 와 의미가 같다. 즉 a-b사이 어떤 문자가 들어간다고 해도 매치된다.

a.b = 'aab' = 'adfafb' != 'abc'

이 때 'a.b'처럼 "." 자체를 매칭시키고 싶다면    a[.]b   처럼 정규식을 표현하면 "a.b"와는 매칭되고 그 사이 다른 문자들에 대해서는 매치되지 않는다.

 

 

 

반복 (*)

 

* 는 반복 개수를 무한대로 허용한다. 

a * t 를 표현식으로 사용하면 앞에 'a'가 0부터 무한대까지 반복하여도 매칭된다. 중요한 점은 0이 포함이기 때문에 a가 없어도 문자열이 매칭된다.

'ca*t' == 'ct' == 'caaaaaat'

 

 

반복 (+)

 

이와 비슷하게 +는 반복을 표현하지만 최소 1번 이상 앞의 문자가 등장해야 매칭이된다 . 

a + t 를 표현식으로 사용하면 앞에 'a'가 1부터 무한대까지 반복하여도 매칭된다.

'ca*t'  == 'caaaaaat'  != 'ct'

 

 

선택 반복 ( { m , n } , ? )

 

{ } 메타 문자를 사용하면 반복횟수를 선택하여서 매칭시킬 수 있다.

{ m, n }. 이라고 한다면  m부터 n사이 안으로 반복하는 문자들에 대해서 매칭된다. 

'ca{2}" ==  'caat'  !=   'cat'                                    // 'c' + a(반드시 2번 반복) + 't'

'ca{2,5}'  == 'caat' == 'caaaat' != 'cat'                // 'c' + a(2-5회 반복) + 't'

 

 

?

 

? 문자는 반복에서 { 0, 1 } 을 의미한다

a b ? c 라고 한다면 'a' + b(있어도 되고 없어도 되고) + 'c'에 대해서 매칭된다.

'ab?c' == 'abc' == 'ac'

 

 

 

 

 

 

 

re 모듈

 

파이썬은 정규 표현식을 지원하기 위해 re ( regular expression)  모듈을 제공한다.  re 모듈은 파이썬에서 기본 라이브러리로 제공되고 있다.

 

>>> import re 
>>> p = re.compile('ab*')

 

라이브러리의 사용 방법은 위와 같다.

re.compile을 사용하여 정규 표현식(위 예에서는 ab*)을 컴파일한다.  

re.compile의 결과로 돌려주는 객체 p(컴파일된 패턴 객체)를 사용하여 그 이후의 작업을 수행할 것이다. 

( 패턴 = 정규식을 컴파일한 결과 ) 

 

패턴 객체에서는 4가지의 메서드를 제공하고 있다.

  • match ()    :  문자열의 처음부터 정규식과 매치되는지 조사
  • search ()   :  문자열 전체를 검색하여 정규식과 매치되는지 조사
  • findall  ()   :   정규식과 매치되는 모든 문자열을 리스트 형식으로 반환
  • finditer()   :   정규식과 매치되는 모든 문자열을 반복 가능한 객체로 반환

# match() , search() 경우 매치되면 match()객체를 반환하고 매치되지 않는다면 None을 반환한다.

 

 

아래 예시를 위해 먼저 문자열을 포함하는 정규식 패턴을 만들어보자!

>>> import re 
>>> p = re.compile('[a-z]+')

 

match

- 문자열의 처음부터 정규식과 매치되는지 조사 


>>> 
m = p.match("python")          # 처음 문자열로 매칭 성공 match() 객체 반환
>>> print(m)

<_sre.SRE_Match object at 0x01F3F9F8>

>>> 
m = p.match("3 python")       # 처음에 숫자가 포함되어 매칭 실패 None 반환
>>> print(m) 

None

위와 같이 매칭 성공/실패 여부에 따라 match()객체나 None을 반환하기 때문에 정규식 프로그래밍은 주로 다음과 같은 흐름을 가진다.

p = re.compile(정규표현식)
m = p.match( 'string goes here' )
if m:
         print('Match found: ', m.group()) 
else:
         print('No match')


# 즉 match의 결괏값이 있을 때만 그다음 작업을 수행하겠다는 것이다.


 

 

search

문자열 처음부터의 검색이 아닌 문자열 전체를 검색 

 


>>> 
m = p.search("python")          # 문자열로 매칭 성공 match() 객체 반환
>>> print(m) 

<_sre.SRE_Match object at 0x01F3F9F8>

>>> 
m = p.search("3 python")       # 문자열 전체를 검색하기 때문에 처음에 3이 등장해도 매치된다/
>>> print(m) 

<_sre.SRE_Match object at 0x01F3F930>

 

 

 

findall

해당하는 정규식과 매칭된 요소를 리스트로 반환한다.

 

>>> result = p.findall("life is too short"
>>> print(result)

['life''is''too''short']

 

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

 

 

 

finditer

finditer는  반복 가능한 객체(iterator object)를 반환한다. 반복 가능한 객체가 포함하는 각각의 요소는 match 객체이다.

 

>>> result = p.finditer("life is too short"
>>> print(result)
<callable_iterator object at 0x01F5E390

>>> for r in result: print(r)
...
<_sre.SRE_Match object at 0x01F3F9F8>
<_sre.SRE_Match object at 0x01F3FAD8>
<_sre.SRE_Match object at 0x01F3FAA0>
<_sre.SRE_Match object at 0x01F3F9F8>

 

 

 

 

 

 

 

match 객체의 메서드

 

수행한 패턴에 대한 반환값을 match 객체의 내부 메서드를 통해서 원하는 정보로 반환값을 받을 수 있다.

 

group() 매치된 문자열을 돌려준다.
start() 매치된 문자열의 시작 위치를 돌려준다.
end() 매치된 문자열의 끝 위치를 돌려준다.
span() 매치된 문자열의 (시작, 끝)에 해당하는 튜플을 돌려준다.

 

 

>>> m = p.match("python")
>>> m.group() 'python' 

>>> 
m.start().    // 항상 0 : match는 시작부터 조사하므로
 0 

>>> 
m.end()
 6 

>>> 
m.span()
(06)

>>> 
m = p.search("3 python"
>>> m.group() 'python' 

>>> 
m.start()
 2 

>>> m.end() 
8 

>>> m.span()
(28)

 

 

 

[모듈 단위로 수행하기]

 

re 모듈을 통해서 표현식의 컴파일과 매칭 작업을 함께 사용할 수 있는데 아래와 가다

 

>>> p = re.compile('[a-z]+')

>>> m = p.match("python")

 

== 이를 re 모듈을 통해 줄인다면 아래와 같아진다 ==

 

>>> m = re.match('[a-z]+', "python")

 

 

위 예처럼 사용하면 컴파일과 match 메서드를 한 번에 수행할 수 있다. 패턴객체를 여러번 사용 할 때는 이 방법보다 re.compile을 사용하는 것이 편하다.

 

 

 

 

컴파일 옵션

 

정규식을 compile하는 경우 지정된 옵션을 통해서 제약사항을 줄 수 있게 한다.

 

  • DOTALL(S) -" . " 이 줄바꿈 문자를 포함하여 모든 문자와 매치할 수 있도록 한다. ( re.S)
  • IGNORECASE(I) - 대소문자에 관계없이 매치할 수 있도록 한다.        (re.I)
  • MULTILINE(M) - 여러줄과 매치할 수 있도록 한다. 각 라인 적용 (^, $ 메타문자의 사용과 관계가 있는 옵션이다.   (re.M)
  • VERBOSE(X) - verbose 모드를 사용할 수 있도록 한다. (정규식을 보기 편하게 만들수 있고 주석등을 사용할 수 있게된다.   (re.X)

옵션을 사용할 때는 re.DOTALL처럼 전체 옵션 이름을 써도 되고 re.S처럼 약어를 써도 된다.

 

 

 

 

 

백슬레시 문제

 

정규식에서는 \ 를 문자열로 받아 들이기 위해 백슬레시를 2개 사용하여 이스케이프 처리를 한다.    '. \\. "

 

그런데 파이썬에서 정규식을 만들어 컴파일하면 실제 파이썬 정규식 엔진에서는 파이썬 문자열 리터럴 규칙에 따라 \\ 이 \ 로 변경되어 결국 \section 에 대해서 컴파일로 전달된다. 

때문에 정규식 엔진에 \\ 문자를 전달하기 위해 파이썬에서는 \\\\ 처럼 백슬레시를 4개 사용한다.

 

이를 해결하기 위해 파이썬 정규식에서는 Raw string 규칙 ( R-string)이 생겨나게 되었다. 

 

.>>> p = re.compile(r'\\section')

위와 같이 정규식 문자열 앞에 r 문자를 삽입하면 이 정규식이 규칙에 의해  \\ 를 \ 쓴 것으로 판단하여 처리하게 된다.

반응형

'Tech Stack > Python' 카테고리의 다른 글

정규표현식 (2)  (0) 2021.08.14
내장함수  (0) 2021.08.10
예외 처리  (0) 2021.08.06
패키지  (0) 2021.08.03
모듈  (0) 2021.08.02