• 정규식을 컴파일할 때 다음 옵션을 사용할 수 있다.
    • DOTALL(S) - .이 줄바꿈 문자를 포함하여 모든 문자와 매치할 수 있도록 한다.
    • IGNORCASE(I) - 대소문자에 관계없이 매치할 수 있도록 한다.
    • MULTILINE(M) - 여러줄과 매치할 수 있도록 한다.(^,$ 메타 문자의 사용과 관계거가 있는 옵션이다.)
    • VERBOSE (X) - verbose 모드를 사용할 수 있도록 한다. (정규식을 보기 편하게 만들 수 있고 주석 등을 사용할 수 있게 된다.)
  • 옵션을 사용할 때는 re.DOTALL처럼 전체 옵션 이름을 써도 되고, re.S처럼 약어를 써도 된다.
  • 위에서 괄호 안에 있는 문자들이 약어이다.

  • DOTALL(S)
    • .메타 문자는 줄바꿈 문자(\n)를 제외한 모든 문자와 매치되는 규칙이 있다. 만약 \n 문자도 포함하여 매치하고 싶다면 re.DOTALL 또는 re.S 옵션을 사용해 정규식을 컴파일하면 된다.
import re
p = re.compile('a.b')
m = p.match('a\nb')
print(m)
None
  • 정규식이 a.b인 경우 문자연 a\nb는 매치되지 않음을 알 수 있다. 왜냐하면 \n은 .메타문자와 매치되지 않기 때문이다. \n 문자와도 매치되게 하려면 다음과 같이 re.DOTALL 옵션을 사용해야 한다.
p = re.compile('a.b',re.DOTALL)
m = p.match('a\nb')
print(m)
<re.Match object; span=(0, 3), match='a\nb'>
  • 보통 re.DOTALL 옵션은 여러 줄로 이루어진 문자열에서 \n에 상관없이 검색할 때 많이 사용한다.

  • IGNORECASE(I)
    • re.IGNORECASE 또는 re.I 옵션은 대소문자와 구별 없이 매치를 수행할 때 사용하는 옵션이다.
p = re.compile('[a-z]+',re.I)
p.match('python')
p.match('Python')
p.match('pYthon')
<re.Match object; span=(0, 6), match='pYthon'>
  • [a-z]+ 정규식은 소문자만을 의미하지만 re.I 옵션으로 대소문자 구별 없이 매치된다.

  • MULTILINE(M)
    • re.MULTILINE 또는 re.M 옵션은 조금 후에 설명할 메타 문자인 ^,$ 와 연관된 옵션이다. 이 메타 문자에 대해 간단히 설명하자면 ^는 문자열의 처음을 의미하고 $는 문자열의 마지막을 의미한다. 예를 들어 정규식이 ^python인 경우 문자열의 처음은 항상 python으로 시작해야 매치되고, 만약 정규식이 python$ 이라면 문자열의 마지막은 항상 python으로 끝나야 매치된다는 의미이다.
import re
p = re.compile('^python\s\w+')
data = """python one
life is too short
python two
you need python
python three"""
print(p.findall(data))
['python one']
  • 정규식 '^python\s\w+'은 python이라는 문자열로 시작하고 그 뒤에 whitespace, 그 뒤에 단어가 와야 한다는 의미이다. 검색할 문자열 data는 여러 줄로 이루어져 있다.
  • 따라서 위와 같은 결과가 반환되는 것이다.
  • ^ 메타 문자에 의해 python이라는 문자열을 사용한 첫 번째 줄만 매치된 것이다.
  • 하지만 ^ 메타 문자를 문자열 전체의 처음이 아니라 각 라인의 처음으로 인식시키고 싶은 경우도 있을 것이다. 이럴 때 사용할 수 있는 옵션이 바로 re.MULTILINE 또는 re.M이다.
import re
p = re.compile("^python\s\w+", re.MULTILINE)

data = """python one
life is too short
python two
you need python
python three"""

print(p.findall(data))
['python one', 'python two', 'python three']
  • re.MULTILINE 옵션으로 인해 ^ 메타 문자가 문자열 전체가 아닌 각 줄의 처음이라는 의미를 갖게 되었다. 이 스크립트를 실행하면 위와 같은 결과가 출력된다.-
  • 즉 re.MULTILINE 옵션은 ^, $ 메타 문자를 문자열의 각 줄마다 적용해 주는 것이다.

  • VERBOSE(X)
    • 이해하기 어려운 정규식을 주석 또는 줄 단위로 구분할 수 있다면 얼마나 보기 좋고 이해하기 쉬울 것이다. 이를 위해 re.VERBOSE 또는 re.X 옵션을 사용하면 된다.
    • 다음 예를 보자
charref = re.compile(r'&[#](0[0-7]+|[0-9]+|x[0-9a-fA-F]+);')
  • 이해하기 어렵다
  • 다음 예를 보자
charref = re.compile(r"""
 &[#]                # Start of a numeric entity reference
 (
     0[0-7]+         # Octal form
   | [0-9]+          # Decimal form
   | x[0-9a-fA-F]+   # Hexadecimal form
 )
 ;                   # Trailing semicolon
""", re.VERBOSE)
  • 첫 번째와 두 번째 예를 비교해 보면 컴파일 된 패턴 객체인 charref는 모두 동일한 역할을 한다. 하지만 정규식이 복잡할 경우 두 번째처럼 주석을 적고 여러줄로 표현하는 것이 훨씬 가독성이 좋다는 것을 알 수 있다.
  • re.VERBOSE 옵션을 사용하면 문자열에 사용된 whitespace는 컴파일할 때 제거된다.(단 []안에 사용된 whitespace는 제외) 그리고 줄 단위로 # 기호를 사용하여 주석문을 작성할 수 있다.

  • 백슬래시 issue
    • 정규 표현식을 파이썬에서 사용할 때 혼란을 주는 요소가 한 가지 있는데 바로 백슬래시이다.
    • 예를 들어보자
    • "\selection"문자열을 찾기 위한 정규식을 만든다고 가정해보자
      \selection
      
    • 이 정규식은 \s 문자가 whitespace로 해석되어 의도한 대로 매치가 이루어지지 않는다.
    • 위 표현은 다음과 동일한 의미이다.
      [\t\n\r\f\v]ection
      
    • 의도한 대로 매치하고 싶다면 다음과 같이 변경해야 한다.
      \\section
      
    • 즉 위 정규식에서 사용한 \ 문자가 문자열 자체임을 알려주기 위해 백슬래시 2개를 상요하여 이스케이프 처리를 해야한다
    • 다라서 위 정규식을 컴파일 하려면 다음과 같이 작성하는 것이 올바르다
p = re.compile('\\section')
  • 그러나 이처럼 정규식을 만들어서 컴파일하면 실제 파이썬 정규식 엔진에는 파이썬 문자열 리터럴 규칙에 따라 \이 \로 변경되어 \section이 전달된다.
  • 결국 정규식 엔진에 \문자를 전달하려면 파이썬은 \\처럼 백슬래시를 4개 사용해야한다.
p = re.compile('\\\\section')
  • 이렇게 해야만 원하는 결과를 얻을 수 있다.
  • 상당히 복잡해보이기에 파이썬 정규식에는 Raw String 규칙이 생겨나게 되었다.
  • 즉 컴파일해야 하는 정규식이 Raw String임을 알려줄 수 있도록 파이썬 문법을 만든 것이다.
  • 방법은 다음과 같다.
p = re.compile(r'\\section')
  • 위와 같이 정규식 문자열 앞에 r문자를 삽입하면 이 정규식은 RawString 규칙에 의하여 백슬래시 2개 대신 1개만 써도 2개를 쓴 것과 동일한 의미를 갖게 된다.
  • 만약 백슬래시를 사용하지 않는 정규식이라면 r의 유무에 상관없이 동일한 정규식이 될 것이다.