본문 바로가기
Python

[Python] 정규표현식 사용하는 방법 - re 모듈 사용방법 및 예제

by A6K 2022. 11. 10.

문자열을 다루는 가장 간단하고 강력한 방법은 정규표현식을 사용하는 것이다. 정규표현식(Regular Expressions)을 통해 복잡한 문자열 처리를 몇 줄의 짧은 코드만으로 간단하게 처리할 수 있다. (정규표현식은 Regex 혹은 정규식으로 줄여서 표현하기도한다) 정규표현식 자체는 파이썬만의 고유기능은 아니다. 다른 프로그래밍 언어에서도 지원되는 기능이다.

메타 문자(Meta Characters)

정규표현식에서 메타 문자들은 특별한 용도로 사용되는 문자들을 말한다. 문자가 가진 원래 의미가 아닌 특별한 의미를 부여받아 사용되는 문자들이 있다. 정규표현식에서 다음과 같은 메타 문자들이 있다.

. ^ $ * + ? { } \ [ ] | ( )

각 메타 문자들이 정규표현식에서 어떤 의미로 사용되는지 알아보자.

문자 클래스 - [ ]

정규표현식에서 대괄호 문자인 [ ]는 대괄호 안에 포함된 문자들 중 하나와 매치됨을 의미한다.

예를 들어

[abc] # a, b, c 세 문자 중 하나와 매치

 

[abc]는 대괄호안에 있는 a, b, c 세가지 문자 중 하나와 매치됨을 의미한다. 만약 문자열 'apple', 'banana', 'mango' 가 있다면 정규표현식 [abc]와 다음과 같이 매칭된다.

  • apple은 'a' 문자가 있으므로 매치
  • banana는 'b' 문자가 있으므로 매치
  • mango는 a, b, c 모두 없으므로 매치되지 않음

대괄호 안에서 하이픈(-) 문자를 이용하면 두 문자의 범위를 지정하게 된다. 예를 들어

[0-9] # 0부터 9까지 숫자
[a-zA-Z] # 대소문자 알파벳

[0-9]는 [0123456789]를 하이픈 문자를 이용해 짧게 쓴 것이다. [a-zA-Z] 역시 알파벳 대소문자들을 나열하지않고 하이픈을 이용해서 범위를 지정해 짧게 쓴 것이다.

대괄호 안쪽에서 꺽쇠(^) 문자를 사용하면 not 의 의미를 갖는다. 예를 들어 [^0-9]는 숫자가 아닌 문자에만 매칭이 된다.

[^0-9] # 숫자가 아닌 문자들에 매칭
[^abc] # a, b, c가 아닌 문자들에 매칭

자주 사용하는 문자 클래스는 대괄호 대신 별도의 표기법으로 표현하기도 한다.

문자 클래스 설명
\d 숫자와 매치, [0-9]와 동일
\D 숫자가 아닌 문자와 매치, [^0-9]와 동일
\w 숫자와 문자에 매치, [a-zA-Z0-9]와 동일
\W 숫자와 문자가 아닌 것에 매치, [^a-zA-Z0-9]와 동일
\s 공백과 매치, [ \t\n\r\f\v]와 동일
\S 공백 문자가 아닌 것과 매치, [^ \t\n\r\f\v]와 동일

모든 문자 - .

정규표현식에서 dot 문자(.)는 줄바꿈 문자인 '\n'을 제외한 모든 문자와 매치된다.

a.b

정규표현식 a.b는 a문자와 b문자 사이에 문자하나가 오면 모두 매칭된다.

a0b # a와 b 사이에 0이 와서 매치
acb # a와 b 사이에 c가 와서 매치
abc # a와 b 사이에 아무문자도 없어서 매치되지 않음

만약 dot 문자 자체를 표현하고 싶으면 대괄호를 이용하면 된다.

a[.]b

0번 이상 반복 - * 

정규표현식에서 * 문자는 바로 앞에 오는 문자가 0번 이상 반복됨을 의미한다. 예를 들어

ca*t

ca*t 라는 정규표현식은 c문자와 t문자사이에 a 문자가 0번 이상 반복되면 매칭된다.

ct      # 매칭
cat     # 매칭
caaaaat # 매칭

1번 이상 반복 - +

정규표현식에서 + 문자는 바로 앞에 오는 문자가 1번 이상 반복됨을 의미한다. 예를 들어

ca+t

ca+t라는 정규표현식은 c문자와 t문자사이에 a 문자가 1번 이상 반복되면 매칭된다.

ct       # 매칭안됨
cat      # 매칭
caaaaaat # 매칭

* 문자와 다른점은 적어도 한번은 등장해야 매칭된다는 점이다.

없거나 하나 존재 - ?

정규표현식에서 ? 문자는 앞에 있는 문자가 없거나 한번만 등장할 때 매칭된다. 예를 들어

ca?t

ca?t이라는 정규표현식은 c문자 뒤, t문자 앞에 a문자가 등장하지 않거나 한번만 등장할 때만 매칭된다.

ct     # 매칭
cat    # 매칭
caaaat # 매칭안됨

반복횟수 지정 - {m, n}

정규표현식에서 {m, n}은 앞에 오는 문자가 최소 m번에서 최대 n번까지 등장해야 매칭된다. 예를 들어

ca{2,3}t

ca{2, 3}t는 a문자가 2번이상 3번이하 반복될때만 매칭된다.

ct      # 매치안됨
cat     # 매치안됨
caat    # 매치
caaat   # 매치
caaaat  # 매치 안됨

{m} 형태로 사용하면 m 번 반복되는 경우만 매칭된다. * 는 {0, }로 고쳐쓸 수 있고, + 는 {1, }로 고쳐쓸 수 있다. 또 ? 는 {0, 1}과 동일하다.

여러개 표현식을 or 연결 - |

| 문자를 이용해서 여러개의 정규표현식을 or 로 연결할 수 있다. 이렇게 연결된 정규표현식 중 하나라도 매칭되면 매칭되는 것으로 간주한다.

a | b | c

예를 들어 a | b | c 는 a 문자 혹은 b 문자 혹은 c 문자 중 하나라도 매치되면 매치된다고 판단한다.

a     # 매치
b     # 매치
c     # 매치
a c   # 매치
a b c # 매치
e     # 매치안됨

문자열의 시작과 종료 ^, $

^ 문자는 문자열의 시작점을 의미하고, $ 문자는 문자열의 종료점을 의미한다.

^a

^a 는 문자열이 시작하고 바로 a 문자가 나오는 경우와 매칭된다.

a    # 매칭
aa   # 매칭
cat  # 매칭안됨

문자열의 마지막 부분을 명시하려면 $ 문자를 쓰면 된다.

a$

a$는 문자열의 마지막에 a문자가 나오고 문자열이 끝났음을 의미한다.

a    # 매칭
aa   # 매칭
cat  # 매칭안됨
cola # 매칭

파이썬 re 모듈

파이썬은 정규 표현식을 지원하기 위해 re(Regular Expression) 모듈을 제공한다. re 모듈은 별도로 설치할 필요는 없고 파이썬이 설치될 때 함께 설치된다.

import re

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

re 모듈을 사용하기 위해 import를 해준다. 사용할 정규식을 문자열 형태로 만들고 re 모듈의 compile() 함수에 인자로 넘긴다. 그러면 정규식을 컴파일한 패턴 객체가 리턴된다. 이 패턴 객체를 이용해서 정규표현식을 사용하면 된다.

패턴 객체를 통해 사용할 수 있는 메소드는 4가지가 있다.

메소드 설명
match() 문자열의 처음부터 정규표현식과 매치되는지 확인
search() 문자열 전체를 검색해서 정규표현식과 매치되는지 확인
findall() 정규식과 매치되는 모든 문자열들을 리스트로 리턴
finditer() 정규식과 매치되는 모든 문자열들을 이터레이터 객체로 리턴

match()

match() 메소드는 문자열의 처음부터 정규식과 매치되는지를 확인한다.

import re

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

m = p.match('cat')
print(m)

n = p.match('1 cat')
print(n)

# <re.Match object; span=(0, 3), match='cat'>
# None

cat 이라는 문자열이 [a-z]+ 정규식에 매칭되는지 확인한다. 매칭되는 경우 match() 메소드는 Match 객체를 리턴한다. '1 cat'이라는 문자열에서는 처음 등장하는 1이라는 숫자가 [a-z]+ 정규식에 부합하지 않으므로 None 이 리턴된다.

match() 메소드가 리턴하는 Match 객체에는 다음과 같은 메소드가 제공된다.

메소드 설명
group() 매치된 문자열 리턴
start() 매치된 문자열의 시작 위치
end() 매치된 문자열의 끝 위치
span() 매치된 문자열의 (시작, 끝) 형태의 튜플 리턴

위 예제에서 다시 적용해보면

import re

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

m = p.match('cat')
print(m.group())
print(m.start())
print(m.end())
print(m.span())

# cat
# 0
# 3
# (0, 3)

search()

search() 메소드는 match() 메소드와 마찬가지로 컴파일한 정규식이 문자열과 매칭되는지 확인한다. match() 메소드와 다르게 search() 메소드는 문자열의 처음부터 무조건 만족해야하는 것은 아니다.

import re

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

m = p.search('cat')
print(m)

n = p.search('1 cat')
print(n)

# <re.Match object; span=(0, 3), match='cat'>
# <re.Match object; span=(2, 5), match='cat'>

match() 메소드에서는 '1 cat'이라는 문자열은 매칭되지 않았다. 시작하는 1이라는 문자가 정규식에 부합되지 않았기 때문이다.

하지만 search() 메소드에서는 매칭된다. 뒤에오는 cat 문자열이 정규식에 부합되기 때문이다.

리턴되는 Match 객체의 사용법은 동일하다.

findall()

finall() 메소드는 정규식과 매치되는 모든 문자열을 리턴해준다.

import re

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

m = p.findall('My cat is cute')
print(m)

# ['y', 'cat', 'is', 'cute']

'My cat is cute' 문자열을 [a-z]+ 정규식의 findall()에 넘겨보면 ['y', 'cat', 'is', 'cute'] 리스트가 나온다. My의 M은 대문자라서 매칭이 안됨을 유의하자.

finditer()

findall()과 유사하다. 다만 매치된 모든 결과를 다루는 Match 객체에 대한 이터레이터를 리턴한다.

import re

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

m = p.finditer('My cat is cute')
for i in m:
    print(i.group())

# y
# cat
# is
# cute

컴파일 옵션

정규식을 패턴으로 컴파일 할 때 사용할 수 있는 몇 가지 옵션이 있다. compile 메소드의 두번째 인자로 RE.옵션 형태로 주면된다.

p = re.compile(regex, re.OPTION)
옵션 설명
DOTALL, S \n 문자까지 정규식의 . 문자에 매칭
IGNORECASE, I 대소문자를 구분하지 않고 매칭
MULTILINE, M 여러 줄의 문자열에 ^와 $ 문자를 적용
VERBOSE, X 더 가독성좋게 정규표현식을 작성

 

파이썬 스크립트 작성에 도움되는 글 모음

파이썬으로 프로그램을 작성할 때 도움되는 글들을 모아본다. 개발환경 [Python] macOS에 파이참 설치 [Python] 파이참 깃허브 연동 [Python] 파이썬 PIP란? [Python] VSCode를 이용한 개발환경 [Python] python3를

hbase.tistory.com

 

댓글