[Python자동화처리] 정규표현식

전보·2020년 5월 30일
0

정규표현식

점프 투 파이썬 : 7장 정규표현식

정규표현식은 문자열을 처리할 때 사용하는 기법으로, 파이썬만의 고유문법이 아니라 문자열을 처리하는 모든 곳에서 사용하는 것이고, 줄여서 "정규식"이라고도 말한다.

문자클래스[ ]

[ ] 안에있는 문자들 중 한개의 문자라도 일치하는 문자가 있으면 "매치한다" 라고 한다.

즉, [abc]는
"a"와 매치
"defore"과 매치
"dude"와 매치되지 않음.

[ ? - ? ] 는 ?의 두문자사이의 범위를 의미한다.

즉, [a-c]는 [abc]이고,
[0-5]는 [012345]를 의미한다.

[a-zA-Z] : 알파벳 모두
[0-9] : 숫자

***문자클래스안에 ^기호는 반대를 의미한다.
즉, [^0-9]는 문자라는 의미.

\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을 제외한 모든 문자를 의미한다.
a.b : "a + 모든문자 + b"
->"aab", "a0b"는 매치, "abc" 불매치. 사이에 아무문자 하나라도 있어야 됨.

  • re.DOTALL : ¥n도 포함 매치.

[.]이렇게 사용되면 "모든문자"라는 의미가 아닌 문자"."그대로를 의미한다.

반복(*)

*바로 앞에 있는 문자가 반복횟수가 0부터 무한대로 반복될 수 있다는 의미.

ca*t

ct : 매치
cat : 매치
caaat : 매치

반복(+)

+바로 앞에 있는 문자가 반복횟수가 1부터 무한대로 반복될 수 있다는 의미.

ca+t

ct : 불매치
cat : 매치
caaat : 매치

반복 ({m,n}, ?)

{3,} : 반복 횟수가 3 이상. //생략된 n은 무한대(2억 개 미만).
{,3} : 반복 횟수가 3 이하. //생략된 m은 0.

1.{m}

ca{2}t

: c + a(반드시 2번 반복) + t

cat : 불매치
caaat : 매치

2. {m, n}

ca{2,5}t

:c + a(2~5회 반복) + t

cat : 불매치
caat : 매치
caaaaat : 매치

3. ?

ca?t

:c + a(있어도 되고 없어도 된다) + t

ct : 매치
cat : 매치
caat : 불매치

, +, ? 메타 문자는 모두 {m, n} 형태로 고쳐 쓰는 것이 가능하지만 가급적 , +, ? 메타 문자를 사용하자.

" * " : {0,}
" + " : {1,}
" ? " : {0, 1}

정규 표현식을 지원하는 re 모듈

import re
p = re.compile('[a-z]+')
  1. match() 문자열의 처음부터 정규식과 매치되는지 조사한다.
m = p.mach("3 python")
print(m)

# 결과 : None
  1. search() 문자열 전체를 검색하여 정규식과 매치되는지 조사한다.
m = p.search("3 python")
print(m)

# 결과 : <re.Match object; span=(2, 8), match='python'>
  1. findall() 정규식과 매치되는 모든 문자열(substring)을 리스트로 돌려준다.
m = p. findall("the 3 python")
print(m)

# 결과 : ['the', 'python']

for r in m:
     print(r)

# 결과 :
# the
# python

단어를 잘라서 각각 [a-z]+ 정규식과 매치해서 리스트로 돌려준다.

  1. finditer() 정규식과 매치되는 모든 문자열(substring)을 반복 가능한 객체로 돌려준다.
m = p.finditer("the 3 python")
print(m)

# 결과 : 
# <callable_iterator object at 0x101e2f070>

for r in m:
     print(r)

# 결과 :
# <re.Match object; span=(0, 3), match='the'>
# <re.Match object; span=(6, 12), match='python'>

match,search 객체의 메서드

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

>>> m = p.search("3 python")
>>> m.group()
'python'
>>> m.start()
2
>>> m.end()
8
>>> m.span()
(2, 8)

코드 축약 가능

>>> p = re.compile('[a-z]+')
>>> m = p.match("python")
위 코드가 축약된 형태는 다음과 같다.

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

컴파일 옵션

  1. VERBOSE(X) - verbose 모드를 사용할 수 있도록 한다. (정규식을 보기 편하게 만들수 있고 주석등을 사용할 수 있게된다.)

1. DOTALL, S

줄바꿈 문자를 포함하여 모든 문자와 매치할 수 있도록 한다.

p = re.compile('a.b', re.DOTALL)
m = p.match('a\nb')
print(m)

# 결과 : <re.Match object; span=(0, 3), match='a\nb'>
>>> 

2. IGNORECASE, I

대소문자에 관계없이 매치할 수 있도록 한다.

>>> p = re.compile('[a-z]', re.I)
>>> p.match('python')
<re.Match object; span=(0, 1), match='p'>
>>> p.match('Python')
<re.Match object; span=(0, 1), match='P'>
>>> p.match('PYTHON')
<re.Match object; span=(0, 1), match='P'>

3. MULTILINE, M

여러줄과 매치할 수 있도록 한다. (^, $ 메타문자의 사용과 관계가 있는 옵션이다)
^는 문자열의 처음을 의미하고, $는 문자열의 마지막을 의미한다.

^python인 경우 문자열의 처음은 항상 python으로 시작해야 매치되고,
python$이라면 문자열의 마지막은 항상 python으로 끝나야 매치된다는 의미이다.

import re

# 정규식 ^python\s\w+은 python이라는 문자열로 시작하고 그 뒤에 whitespace, 그 뒤에 단어가 와야 한다는 의미이다. 
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이라는 문자열을 사용한 첫 번째 줄만 매치된다.

re.MULTILINE 또는 re.M이
^ 메타 문자를 문자열 전체의 처음이 아니라 각 줄의 처음으로 인식하게 한다.
p = re.compile("^python\s\w+")
p = re.compile("^python\s\w+", re.MULTILINE) 로 고친후 실행하면,
결과는
['python one', 'python two', 'python three'] 가 된다.

4. VERBOSE, X

charref = re.compile(r'&[#](0[0-7]+|[0-9]+|x[0-9a-fA-F]+);')

re.VERBOSE 옵션을 사용하면 문자열에 사용된 whitespace는 컴파일할 때 제거된다.
(단 [ ] 안에 사용한 whitespace는 제외).
그리고 줄 단위로 #기호를 사용하여 주석문을 작성할 수 있다.

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)

백슬래시 문제

\section = [ \t\n\r\f\v]ection
\section을 문자 그대로 매치하고 싶다면 \\section 로 변경해야한다.

따라서 "\section" 문자열을 찾기 위한 정규식을 컴파일하려면
>>> p = re.compile('\\section')
이렇게 작성해야한다.

그렇다면, "\section"을 나타내고 싶을 때는
>>> p = re.compile('\\\\section')로 표현해야하고, \이 계속 반복되는 정규식이라면 너무 복잡해진다.

그래서 >>> p = re.compile(r'\\section')
정규식 문자열 앞에 r 문자를 삽입하면 이 정규식은 Raw String 규칙에 의하여 백슬래시 2개 대신 1개만 써도 2개를 쓴 것과 동일한 의미를 갖게 된다.

백슬래시를 사용하지 않는 정규식이라면 r의 유무에 상관없이 동일한 정규식이 될 것이다.

profile
엉망진창

0개의 댓글