CodingTest/Python Grammar Notes

[Python] 정규 표현식 (Regular Expression, RE)

조 수빈 2022. 10. 11. 17:17

🔍 Regular Expression HOWTO

문자열 문제(백준의 9342)를 푸는 도중 감이 잡히지 않아 다른 사람들의 풀이를 참고하였는데, 정규 표현식을 사용하면 쉽게 풀 수 있는 문제였다.

이론은 대학교 수업 시간에 배운 바 있지만, 파이썬에서는 어떻게 사용하는지 몰랐기에 이참에 정리해 보고자 한다.

공식 문서점프 투 파이썬 등을 참고하여 작성하였다.
모든 내용을 다룬 것은 아니기에, 공식 문서 등을 참고하면 좋을 것 같다.


📃 정규 표현식(Regular Expressions)

정규 표현식(Regular Expressions)은 간단히 정규식, RE, regexes 또는 regex 패턴 등으로 줄여 부름

정규 표현식은 특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어

쉽게 말해 프로그래밍에서 문자열을 다룰 때, 문자열의 일정한 패턴을 표현하는 일종의 형식 언어를 말하며, 복잡한 문자열을 처리할 때 사용하는 기법이라 할 수 있음


💬 메타 문자

정규 표현식에서 사용하는 메타 문자(원래 그 문자가 가진 뜻이 아닌 특별한 용도로 사용하는 문자)

. ^ $ * + ? { } [ ] \ | ( )
메타 문자 의미
^ (시작) 문자열의 맨 처음과 일치함을 의미(시작의 의미)
$ (끝) 문자열의 끝과 매치함을 의미(끝의 의미)
[ ] (문자 클래스) 일치시키려는 문자 집합인 문자 클래스를 지정하는 데 사용
. (Dot) 줄바꿈 문자인 \n을 제외한 모든 문자와 매치됨을 의미
* (반복) * 바로 앞에 있는 문자가 0부터 무한대로 반복될 수 있다는 의미
+ (반복) + 는 최소 1번 이상 반복될 때 사용
반복 ({m,n}, ?) 반복 횟수를 고정할 수 있음
| (or) or과 동일한 의미, A|B => A 또는 B

자세한 의미와 사용 방법은 아래에 정리

🔹 문자 클래스 [ ]

◻ 문자 클래스로 만들어진 정규식은 [ ] 사이의 문자들과 매치 라는 의미를 가짐
◻ [ ] 사이에는 어떤 문자도 들어갈 수 있음
ex) [abc]는 "a, b, c" 중 한 개의 문자와 매치를 의미
      - "a"는 매치 O
      - "before"은 정규식과 일치하는 문자 "b"가 있으므로 매치 O
      - "dude"는 a, b, c 중 어느 하나도 포함하고 있지 않으므로 매치 X

◻ [ ] 안의 두 문자 사이에 하이픈(-)을 사용하여 두 문자 사이의 범위를 표현할 수 있음
ex) [a-c]는 [abc]와 같음, [0-5]는 [012345]와 같음
      [a-zA-Z] : 알파벳 모두    [0-9] : 숫자

◻ [ ] 안에 ^ 메타 문자를 사용할 경우 반대의 의미를 가짐
ex) [^0-9]는 숫자가 아닌 문자를 의미

🔹 .(Dot)

Dot(.) 메타 문자는 줄바꿈 문자인 \n을 제외한 모든 문자와 매치됨을 의미함
ex) a.b 는 "a + 모든 문자 + b"를 의미, a와 b 사이 어떤 문자가 들어가도 모두 매치된다는 의미
      - "aab"는 매치 O
      - "a0b"는 매치 O
      - "abc"는 "a"문자와 "b"문자 사이에 어떤 문자라도 하나는 있어야 하는 이 정규식과 일치하지 않으므로 매치 X

🚫 주의  
문자 클래스 [ ] 안의 . 은 문자 . 그대로를 의미함!!  
ex) a[.]b 는 "a.b" 문자열과 매치 O, "a0b" 문자열과는 매치 X

🔹 반복 (* + {m} {m, n} ?)

* + {m} {m, n} ? 5가지 메타 문자가 있음

*

    - * 바로 앞의 문자가 0회 이상 반복될 수 있음을 의미
    - ex) ca*t => ct cat caat caaat 등 가능

+

    - 은 0부터지만 +는 최소 1번 이상을 의미
    - ex) ca
t => ct는 불가능!!, cat caat caaat 등 가능

{m}

    - 반복 횟수가 m인 경우를 의미
    - ex) ca{2}t => caat

{m, n}

    - 반복 횟수가 m부터 n까지임을 의미
    - m 또는 n을 생략할 수 있으며, m을 생략하면 n 이하, n을 생략하면 m 이상의 의미를 가짐
    - ex) ca{2,5}t => caat caaat caaaat caaaaat 가능
    - ex) ca{,5}t => ct cat caat caaat caaaat caaaaat 가능
    - ex) ca{2,}t => caat caaat caaaat caaaaat ... caaaaaaaaaaaaaaat ... 가능

?

    - ? 메타문자가 의미하는 것은 {0, 1}
    - ex) ab?c => ac abc 가능, b가 있어도 되고 없어도 된다는 의미


🐍 파이썬에서의 정규식

파이썬에서는 re(regular expression의 약어) 모듈을 사용하여 정규 표현식을 사용할 수 있음!

import re
p = re.compile('abc*')

re.compile을 사용하여 정규 표현식을 컴파일 함, 그의 결과로 돌려주는 객체(p)는 패턴 객체


👀 문자열 검색

위의 컴파일된 패턴 객체를 사용하여 문자열 검색을 수행할 수 있음
컴파일된 패턴 객체는 아래의 4가지 메서드를 제공함

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

🔹 match()

  • match 메서드는 문자열의 처음부터 정규식과 매치되는지 조사하며, 매치될 때는 match 객체를, 매치되지 않을 때는 None을 리턴함

      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
    
      # 아래와 같이 많이 사용함
      p = re.compile(정규표현식)
      m = p.match( 'string goes here' )
      if m: # match의 결괏값이 있을 때만 그 다음 작업을 수행함
          print('Match found: ', m.group())
      else:
          print('No match')

🔹 search()

  • 문자열의 처음부터가 아닌 문자열 전체를 검색하여 매치되는지 조사하며, match 메서드와 동일하게 매치될 때는 match 객체를, 매치되지 않을 때는 None을 리턴함

      import re
      p = re.compile('[a-z]+')
    
      m = p.search("python")
      print(m) # <re.Match object; span=(0, 6), match='python'>
    
      # match 메서드와 다르게 문자열 전체를 검색하므로 매치 O
      m = p.search("3 python")
      print(m) # <re.Match object; span=(2, 8), match='python'>

🔹 findall() & finditer()

  • findall 메서드는 문자열의 단어를 각각 정규식과 매치해서 리스트로 리턴함

      import re
      p = re.compile('[a-z]+')
    
      result = p.findall("life is too short")
      print(result) # ['life', 'is', 'too', 'short']
  • finditer 메서드는 findall과 동일하지만 반복 가능한 객체를 돌려줌, 반복 가능한 객체가 포함하는 각각의 요소는 match 객체

      import re
      p = re.compile('[a-z]+')
    
      result = p.finditer("life is too short")
      print(result) # <callable_iterator object at 0x01F5E390>
    
      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'>

🛠️ match 객체의 메서드

match 메서드와 search 메서드를 수행한 결과로 match 객체가 리턴된다고 했음

match 객체의 메서드를 사용하면 우리가 원하는 값(문자열, 인덱스 등)을 알아낼 수 있음!

Method 목적
group() 매치된 문자열을 돌려줌
start() 매치된 문자열의 시작 위치를 돌려줌
end() 매치된 문자열의 끝 위치를 돌려줌
span() 매치된 문자열의 (시작, 끝)에 해당하는 튜플을 돌려줌
import re
p = re.compile('[a-z]+')

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

m.group() # 'python'
m.start() # 0
m.end() # 6
m.span() # (0, 6)

# search
m = p.search("3 python")

m.group() # 'python'
m.start() # 2
m.end() # 8
m.span() # (2, 8)