복잡한 문자열을 처리할 때 사용하는 기법으로, 형식언어(formal lanauage)이다. 파이썬 분만 아니라, 문자열을 처리하기 위한 곳에서는 모두 사용된다고 볼 수 있다. 정규표현식은 정규식이라고도 한다.
주민등록 번호를 포함한 보안에 민감한 텍스트 데이터가 있다. 이 때, 주민등록번호를 가명처리 하기 위해서 뒷자리를 모두 * 문자로 변경하고자 한다.
반면, 정규식을 사용하면 다음처럼 훨씬 간편하고 직관적인 코드를 작성할 수 있다. 아직 정규식 사용 방법을 배우지 않았으므로 눈으로만 살펴보자.
정규식을 사용하지 않는 경우에는 아래코드와 같이 문자 라이브러리를 활용해서 문자를 변활한 것이다.
.split()
메서드를 사용해 공백으로 분할한다.*
로 변환한..join()
으로 조합한다.data = """
lee 800905-2049118
hwang 700905-1059119
"""
result = []
for line in data.split("\n"):
word_result = []
for word in line.split(" "):
if len(word) == 14 and word[:6].isdigit() and word[7:].isdigit():
word = word[:6] + "-" + "*******"
word_result.append(word)
result.append(" ".join(word_result))
print("\n".join(result))
>>
lee 800905-*******
hwang 700905-*******
위의 코드에서는 split
, join
, for loop
등 여러 메서드를 사용하여 여러 줄의 코드를 작성하여 문자를 변환하였다. 그러나, 정규표현식을 사용하면 아래와 같이 간단하게 코드를 줄일 수 있다.
re
: 파이썬의 정규표현식 패키지 (패키지 링크)import re
data = """
lee 800905-1049118
hwang 700905-1059119
"""
pat = re.compile("(\d{6})[-]\d{7}")
print(pat.sub("\g<1>-*******", data))
>>
lee 800905-*******
hwnag 700905-*******
원래 문자의 의미가 아닌 특별한 의미를 갖는 문자이다. 아래는 메문자들이다.
.
^
$
*
?
{ }
[ ]
\
|
( )
[ ]
character class[
, ]
문자 사이에 매치되는 문자를 찾을 수 있다. 이 때, 괄호 안에 포함되는 문자 어떤 것이든 찾아 낸다.
-
은 문자사이의 범위를 의미한다.
^
은 not을 의미하고, ~을 제외한다는 뜻이다.
[abc]
[a-c]
(=[abc])
[^a-c]
(=[^abc])
문자 클래스 표현
- \d : 숫자와 매치 - [0-9]
- \D : 숫자를 제외하고 매치 - [^0-9]
- \s : 공백(whitespace) 문자 매치 - [
\t\n\r\f\v]
(은 white space)
- \S : 공백(whitespace) 문자를 제외하고 매치 - [^
\t\n\r\f\v]
- \w : 문자+숫자(alphanumeric)와 매치 - [a-zA-Z0-9
_
]- \W : 문자+숫자(alphanumeric)를 제외하고 매치 - [^a-zA-Z0-9
_
]
※ 여기서 소문자와 대문자는 서로 반대로 의미함
이스케이프 코드(escape code)
프로그래밍을 위해 미리 정의해둔 문자 조함
- \n : 문자열 안에서 줄을 바꿀 때 사용
- \t : 문자열 사이에 탭 간격을 줄 때 사용
- \r : 캐리지 리턴(줄 바꿈, 커서를 현재 줄의 가장 앞으로 이동)
- \f : 폼 피드(줄 바꿈, 커서를 다음 줄로 이동)
- \b : 백 스페이스
.(dot)
\n
을 제외한 모든 문자와 매치한다
.
, \n
도 매치a
.b
: a
+ 모든 문자
+ b
.
에 매치.
에 매치.
에 매치되지만, c가 일지하지 않음a
[.]b
: a
+ .
+ b
.
는 다르다.*
문자+
바로 앞에 있는 문자가 최소 한번 무한대로 반복될 수 있음을 의미한다.
+
문자+
바로 앞에 있는 문자가 무한대로 반복될 수 있음을 의미한다.
{}
반복 회수를 m에서 n번 까지로 제한하기 위해 사용한다.
{n}
무조건 n번 반복
{m, n}
{1,}
== +
, {0,}
== *
ab{2}c
ab{2,5}c
?
{0,1}
의미하며, 바로 앞에 문자가 있어도 되고 없어도 된다.
ab?c
파이썬에서 정규표현식을 지원하는 모듈이다.
import re
p=re.compile('ab*')
match()
문자열이 처음부터 정규식과 매치되는지 조사search()
문자열 전체를 검색하여 정규식과 매치되는지 조사findall()
정규식과 매치되는 모든 하위 문자열(substring)을 리스트로 리턴finditer()
정규식과 매치되는 모든 하위 문자열(substring)을 반복 가능한 객체로 리턴정규식은 패턴 검색이라고 볼 수 있다. 다음 패턴을 선언하여 문자열을 검색하여 매치해 보자.
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( '조사할 문자열' )
if m:
print('Match found: ', m.group())
else:
print('No match')
m = p.search("python")
print(m)
>>
<re.Match object; span=(0, 6), match='python'>
m = p.match("3 python")
print(m)
>>
<re.Match object; span=(2, 8), match='python'>
아래 문자의 인덱스는
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
l i f e ` ` i s ` ` t o o ` ` s h o r t
result = p.findall("life is too short")
print(result)
>> ['life', 'is', 'too', 'short']
reuslt = p.finditer("life is too short")
print(result)
>>
<callable_iterator object at 0x01F5E390>
...
<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'>
m = p.match("python")
m.group()
>>
'python'
m.start()
>>
0
m.end()
>>
6
m.span()
>>
(0, 6)
.
는 줄바꿈 문자를 포함해 모든 문자와 매치^
, $
(메타 문자)와 관계 있음r문자를 사용하여 raw string규칙에 의해 역슬래시를 2번쓴 효과를 낸다.
// p1과 p2는 동일한 표현
p1 = re.compile('\\\\section')
p2 = re.compile(r'\\section')
Reference
[1] https://wikidocs.net/1669
[2] https://pypi.org/project/regex/