본문 바로가기
SK Shieldus Rookies 19th/인프라 활용을 위한 파이썬

[SK shieldus Rookies 19기][Python] - 정규 표현식

by En_Geon 2024. 3. 19.

1. 정규 표현식

복잡한 문자열을 처리할 때 사용하는 기법, 줄여서 정규식이라고도 말한다.

 

주민번호 뒷자리를 바뀔 때  *이 나오는 것을 정규식으로 표현할 수 있다.

 

 

1) 시작

 

(1) 메타 문자

원래 그 문자가 가긴 뜻이 아니라 특별한 의미를 가진 문자를 의미

 

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

 

(2) [ ] 문자 클래스

문자 클래스로 만들어진 정규식은 '[' 와 ']' 사이의 문자들과 매치라는 의미

 

  • 문자 클래스를 만드는 메타 문자인 [ ] 사이에는 어떤 문자도 들어갈 수 있다.
  • 정규식이 [abc]라면 'a, b, c" 중 한 개의 문자와 매치라는 뜻이다.

 

정규식 문자열 매치 여부 설명
[abc] a O "a"는 정규식과 일치하는 문자인 "a"가 있으므로 매치
before O "before"는 정규식과 일치하는 문자인 "b"가 있으므로 매치
dude X "dude"는 정규식과 일치하는 문자인 a, b, c 중 어느 하나도 포함하고 있지 않으므로 매치되지 않음

 

 

(3) - 문자 클래스

[ ] 안의 두 문자 사이에 하이픈(-)을 사용하면 두 문자 시이의 범위를 의미

 

  • [a-c]는 [abc], [0-5]는 [012345]와 같다.
  • [a-zA-Z]는 모든 알파벳 의미
  • [0-9]는 모든 숫자

주의해야 할 메타 문자는 ^이다. 문자 클래스 안에 ^ 메타 문자를 사용할 경우에는 반대(not)라는 의미를 갖는다.

[^0-9]라는 정규식은 숫자가 아닌 문자만 매치된다.

 

  • 자주 사융하는 문자 클래스
정규 표현식 설명
\d 숫자와 매치, [0-9]와 동일한 표현식
\D 숫자가 아닌 것과 매치, [^0-9]와 동일한 표현식
\s 화이트스페이스 문자와 매치, [ \t\n\r\f\v]와 동일한 표현식, 맨 앞의 빈칸은 공백 문자(space)를 의미
\S 화이트스페이스 문자가 아닌 것과 매치, [^ \t\n\r\f\v]와 동일한 표현식
\w 문자 + 숫자와 매치, [a-zA-Z0-9_]와 동일한 표현식
\W 문자 + 숫자가 아닌 문자와 매치 [^a-zA-Z0-9_]와 동일한 표현식

 

  • 화이트스페이스 문자란 스페이스, 탭, 줄바꿈과 같은 공백 문자를 의미

 

(4) .[dot] 문자 - \n을 제외한 모든 문자

정규식 .(dot) 메타 문자는 줄 바꿈인 \n을 제외한 모든 문자와 매치

 

  • a.b는 "a + 모든_문자 + b"를 의미
  • a와 b라는 문자 사이에 어떤 문자가 들어가도 모두 매치된다는 의미

 

정규식 문자열 매치 여부 설명
a.b aab O "aab"는 가운데 문자 "a"가 모든 문자를 의미하는 .과 일치하므로 정규식과 매치
a0b O "a0b"는 가운데 문자 "0"가 모든 문자를 의미하는 .과 일치하므로 정규식과 매치
abc X "abc"는 "a" 문자와 "b" 문자 사이에 어떤 문자라도 하나는 있어야 하는 이 정규식과 일치하지 않으므로 매치되지 않음

 

 

a[.]b처럼 [ ] 안에 . 문자를 쓰면 '.' 문자 그대로를 의미한다. 이 정규식의 의미는 "a + . + b"가 된다.

따라서 정규식 a[.]b는 "a.b" 문자열과 매치되고 "a0b" 문자열과는 매치되지 않는다.

 

(5) * 문자

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

 

  • * 메터 문자의 박복 개수가 무한대라고 했지만, 메모리 용량에 한계가 있어 실제로는 약 2억 개라고 한다.

 

정규식 문자열 매치 여부 설명
ca*t ct O "a"가 0번 반복되어 매치
cat O "a"가 0번 이상 반복되어 매치(1번 반복)
caaat O "a"가 0번 이상 반복되어 매치(3번 반복)

 

 

(6) + 문자

+는 최소 1번 시상 반복될 때 사용

 

정규식 문자열 매치 여부 설명
ca+t ct X "a"가 0번 반복되어 매치되지 않음
cat O "a"가 1번 이상 반복되어 매치(1번 반복)
caaat O "a"가 1번 이상 반복되어 매치(3번 반복)

 

 

 

(7) { } 문자

반복 횟수를 고정할 수 있는 문자

 

 

  • {M}
정규식 문자열 매치 여부 설명
ca[2]t cat X "a"가 1번만 반복되어 매치되지 않음
caat O "a"가 2번 반복되어 매치

 

앞 문자를 반드시 2번 반복을 의미

 

 

  • {m, n}
정규식 문자열 매치 여부 설명
ca[2, 5]t cat X "a"가 1번만 반복되어 매치 되지 않음.
caat O "a"가 2번 반복되어 매치
caaaaat O "a"가 5번 반복되어 매치

 

앞 문자를 2~5화 반복

 

 

(8) ? 문자

? 메타 문자는 {0,1}을 의미

 

 

정규식 문자열 매치 여부 설명
ab?c abc O "b"가 1번 사용되어 매치
ac O "b"가 0번 사용되어 매치

 

  • "a + b가_있어도_되고_없어도_됨+ c"
  • b 문자가 있거나 없거나 둘 다 매치되는 경우

 

2) re모듈

정규 표현식을 지원하기 위해 re 모듈을 제공

 

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

 

 

3) 정규식을 이용한 문자열 검색

 

메서드 목적
match 문자열의 처음부터 정규식과 매치되는지 조사
search 문자열 전체를 검색하여 정규식과 매치되는지 조사
findall 정규식과 매치되는 모든 문자열을 리스트로 리턴
finditer 정규식과 매치되는 모든 문자열을 이터레이터 객체로 리턴

 

 

(1) match

정규식과 100% 일치하면 리턴, 일치하지 않으면 None 리턴

 

import re
p = re.compile('[a-z]+')		# 소문자가 한 번 이상 나오는 것

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

 

  • 출력 : <re.Match object; span=(0, 6), match='python'>

 

 

import re
p = re.compile('[a-z]+')		# 소문자가 한 번 이상 나오는 것

m = p.match('3 python')
print(m)

 

  • 처음에 나오는 문자 3이 정규식에 부합되지 않으므로 None 리턴

 

  • match 객체의 메서드
메서드 목적
group 매치된 문자열을 리턴
start 매치된 문자열의 시작 위치를 리턴
end 매치된 문자열의 끝 위치를 리턴
span 매치된 문자열의 (시작, 끝)에 해당하는 튜플을 리턴

 

 

(2) search

문자열을 검색해 일치하는 문자열이 있으면 문자열을 리턴

 

import re
p = re.compile('[a-z]+')		# 소문자가 한 번 이상 나오는 것

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

 

  • 출력 : <re.Match object; span=(0, 6), match='python'>

위 match와 동일한 출력을 한다.

 

 

import re
p = re.compile('[a-z]+')		# 소문자가 한 번 이상 나오는 것

m = p.search('3 python')
print(m)

 

  • 출력 : <re.Match object; span=(2, 8), match='python'>

search는 문자열의 처음부터 검색하는 것이 아니라 문자열 전체를 검색하기 때문에 "3" 이수의 "python" 문자열가 매치

 

 

(3) findall

매치되는 모든 값을 찾아 리턴

 

import re
p = re.compile('[a-z]+')		# 소문자가 한 번 이상 나오는 것

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

 

  • 출력 : ['life', 'is', 'too', 'short']

 

(4) finditer

findall과 동일하지만, 그 결과로 이터레이터 객체를 리턴
이터레이터 객체가 포함하는 각각의 요소는 match 객체

 

import re
p = re.compile('[a-z]+')		# 소문자가 한 번 이상 나오는 것

result = p.finditer('life is too short')
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'>

 

4. 컴파일 옵션

 

옵션 이름 약어 설명
DOTALL S .(dot)이 줄 바꿈 문자를 포함해 모든 문자와 매치될 수 있게 한다.
IGNORECASE I 대소문자에 관계없이 매치될 수 있게 한다.
MULTILINE M 여러 줄과 매치될 수 있게 한다. ^, $ 메타 문자 사용과 관계있는 옵션
VERBOSE X verbose 모드를 사용할 수 있게 한다. 정규식을 보기 편하게 만들 수 있고 주석 등을 사용할 수 있게 된다.

 

 

1) DOTALL, S

 

. 메타 문자는 줄 바꿈 문자(\n)를 제외한 모든 문자와 매치되는 규칙이 있다. \n 문자도 포함하여 매치하고 싶다면 re.DOTALL 또는 re.S 옵션을 사용하면 된다.

 

import re

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

대소문자 구별 없이 매치를 수행할 때 사용하는 옵션

 

import re

p = re.compile('[a-z]+', re.I)
print(p.match('python'))
print(p.match('Python'))
print(p.match('PYTHON'))

 

  • [a-z]+ 정규식은 소문자만을 의미하지만, re.I 옵션으로 대소문자 구별 없이 매치
  • 모든 문자열이 매치돼 출력됨

 

3) MULTILINE, 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이라는 문자열로 시작하고 그 뒤에 화이트스페이스, 그 뒤에 단어가 와야 한다는 의미
  • ^ 메타 문자에 의해 python이라는 문자열을 사용한 첫 번째 줄만 매치

 

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']
  • MULTILINE 옵션으로 인해 ^ 메타 문자가 문자열 전체가 아닌 각 줄의 처음이라는 의미를 가짐

 

4) VERBOSE, X

정규식을 주석 또는 줄 단위로 구분하는 옵션

 

import re

charref = re.compile(r"""
 &[#]                # Start of a numeric entity reference
 (
     0[0-7]+         # Octal form           8진수
   | [0-9]+          # Decimal form         10진수
   | x[0-9a-fA-F]+   # Hexadecimal form     16진수
 )
 ;                   # Trailing semicolon
""", re.VERBOSE)

 

  • 정규식이 복잡할 경우, 주석을 적고 여러 줄로 표현하는 것이 훨씬 가독성이 좋다.
  • VERBOSE 옵션을 사용하면 문자열에 사용된 화이트스페스는 컴파일할 때 제거
  • 단, [ ] 안에 사용한 화이트스페이스는 제외

 

 

댓글