· 정규 표현식
정규 표현식 또는 정규식은 대량의 문자열에서 특정 문자열을 추출하거나 특정 단어를 확인하거나 원하는 문자열을 참조, 수정 등을 할 때 사용하며 입력자료의 오류 검사 등을 하기 위한 기법이다.
이는 파이썬에서만 사용되는 것이 아니라 javascript, java, VB, C 등 다양한 언어에서도 공통으로 사용하기 때문에 문자열을 처리할 수 있는 프로그램에서 사용한다.
주민등록의 예시 1. 전체 텍스트를 공백 문자로 나눈다.(split) 2. 나누어진 단어가 주민등록 형식인지 파악한다. 3. 단어가 주민등록번호 형식이라면 뒷자리를 *로 변환 4. 나뉜 단어를 다시 조합한다. |
[출처] - 점프 투 파이썬 : 주민등록 예시
<정규 표현식 없이 사용하는 경우>
data = """park 800905-1049118
kim 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():
# isdigit() : 숫자인지 아닌지 판단
word = word[:6] + "-" + "*******"
word_result.append(word)
result.append(" ".join(word_result))
print("\n".join(result))
park 800905-******* kim 700905-******* |
<정규 표현식을 사용하는 경우>
import re
data = """
park 800905-1049118
kim 700905-1059119
"""
pet = re.compile("(\d{6}[-]\d{7})") # \d{n} : n개의 숫자로 지정하는 정규식
print(pet.sub("\g<1>-*******", data)) # \g<n> : n이라는 그룹이름으로 참조
park 800905-1049118-******* kim 700905-1059119-******* |
· 메타 문자
. ^ $ * + ? {} [] \ | ()
메타 문자라는 것은 특수한 의미를 갖고 있는 문자를 말한다.
· 문자 클래스 [ ]
[ ] 사이에 매치(Match)라는 의미를 갖는다.
즉, [abc]라고 하면 a, b, c 중 한 개의 문자와 매치 한다는 뜻이다.
즉 a, b, c가 들어간 문자는 전부 매치가 된다는 뜻이다.
[ ] 안의 두 문자 사이에 하이픈(-)을 사용하면 두 문자 사이의 범위(from - to)를 의미한다.
한글을 전부 표현하고자 할 때 [가-힣]이라고 하면 모든 한글을 의미하게 된다.
반대로 숫자를 모두 표현할 때 [0-9]라고 하면 모든 숫자를 의미한다.
ex)
[a-zA-Z] : 모든 알파벳
[0-9] : 모든 숫자
[가-힣] : 모든 한글
다만 문자 클래스 안에는 한 가지 주의해야 하는 문자가 있는데 '^'이다.
이것은 not이라는 의미이다.
(단, 어떻게 사용하느냐에 따라 not이 될 수도 있고 반드시 포함이라는 의미를 가질 수 있다.)
예를 들어 [^0-9]라는 정규 표현식은 숫자가 아닌 문자만 매치한다 라는 뜻이다.
※ 자주 사용하는 문자 클래스
정규 표현식 |
설명 |
|
\d |
숫자와 매치, [0-9]와 동일 |
|
\D |
숫자가 아닌 것과 매치, [^0-9]와 동일 |
|
\s |
whitespace 문자(space나 tab처럼 공백을 표현하는 문자)와 매치 [\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]와 동일 |
|
\g<그룹명> | 특정 그룹으로 묶어준다. -> 함축 |
|
^ | ^ 문장 앞에 사용하며 해당 문장 패턴으로 시작하는 것만 선택 | ^안녕 : '안녕'으로 시작해야만 한다. ex) 안녕하세요. 안녕하시오. 안녕하쇼 ... 등 |
$ | 문장 마지막에 사용하며 해당 패턴으로 종료되어야 한다. | |
[문자열] | 문자열 중 하나 이상 포함된 것을 반환 | Python, pycham 등이 있을 때 [Pp]라고 하면 P와 p로 시작하는 단어들을 추출 |
[^문자열] | 위에 결과의 반대를 반환한다. 즉, 제외하고 싶은 문자를 넣어준다. | 위의 예시를 다시 사용하면 P, p를 제외하고 모든 문자들을 선택한다. |
| | [패턴1] | [패턴2] : 두 패턴 중 하나. OR을 뜻한다. | i | j : i 또는 j 패턴 |
? | [패턴]? : 해당 패턴의 해당하는 것이 있다면 출력하고 해당하지 않는 다면 공백으로 출력한다. 즉, 0 or 1 매칭이다. |
[0-9]? 라고 조건을 걸면 숫자를 전부 출력하고 숫자가 아닌 것들은 공백으로 출력해준다. |
+ | [패턴]+ : 1개 이상 존재하는 것만 출력한다. |
|
{n} | 패턴{n} : 앞 패턴이 n번 반복해서 나타나는 경우를 출력 | \d{2} : 숫자를 2개씩 출력 |
{n, m} | 패턴{n, ,m} : 패턴이 최소 n번, 최대 m번인 경우 출력 | \d{1, 3} : 1자리 ~ 3자리 숫자 출력 |
. | new line, \n 을 제외한 모든 문자 |
대문자와 소문자는 서로 반대되는 것을 알 수 있다.
· Dot(.)
정규 표현식 Dot(.) 메타 문자는 줄바꿈 문자인 \n을 제외한 모든 문자와 매치됨을 의미한다.
예를 들어 'a.b'라고 하면 a와 b라는 문자 사이에 어떤 문자가 들어와도 모두 매치된다는 의미이다.
"a + 모든 문자 + b"
import re
data = "aab asdfsadfb a0b 날씨가 많b이 a.b더vbc워1요a."
print(re.findall('a[.]b', data))
print(re.findall('a.b', data))
print(re.findall('a....b', data))
['a.b'] ['aab', 'a0b', 'a.b'] ['a.b더vb'] |
· 반복(*)
ca*t
위와 같이 정규식으로 표현하면 *앞에 있는 문자 a가 0부터 무한대로 반복될 수 있다는 의미이다.
(메모리에서 2억개정도로 한정)
즉 위의 정규식에 매칭되는 글자들은 ct(0번 반복), cat(1번 반복), caaaaaaaat(여러번 반복) 등이 매칭이 된다.
반복되는 문자를 축출할 때 사용된다.
data2 = "uraaaaaaaaaa uurraraa"
print(re.findall("ur*a", data2))
['ura', 'urra'] |
· 반복(+)
반복을 나타내는 다른 문자는 +가 있다. +는 최소 1번 이상 반복할 때 사용한다.
즉, *는 0부터라면 +는 최소 1부터인 것이다.
예를 들어 ca+t라고 하면 a가 1번 이상 반복되면 매치인 것이다.
data = "aab asdfsadfb a0b 날씨가 많b이 a.b더vbc워1요a."
print(re.findall("ab*", data))
['a', 'ab', 'a', 'a', 'a', 'a', 'a'] |
· 반복({m, n}, ?)
반복 횟수를 3회만 또는 1회부터 3회까지만 등으로 제한하는 방법도 있다.
{}는 메타 문자를 사용하여 반복 횟수를 고정할 수 있다.
{m, n} 정규식을 사용하면 m부터 n까지 매치할 수 있다. 또는 m or n을 생략할 수 있다.
{3,}라고하면 반복 횟수가 3회 이상인 것이고, {,3}이라고 하면 반복 횟수가 3회 이하인 것을 의미한다.
생략된 m은 0과 동일하고, 생략된 n은 무한대와 동일하다.
import re
data = "aab asdfsadfb a0b 날씨가 많b이 a.b더vbc워1요a."
print(re.findall("[a-z]{1,3}", data))
data2 = "uraaaaaaaaaa uurraraa"
print(re.findall("[a-z]{1,3}",data2))
['aab', 'asd', 'fsa', 'dfb', 'a', 'b', 'b', 'a', 'b', 'vbc', 'a'] ['ura', 'aaa', 'aaa', 'aaa', 'uur', 'rar', 'aa'] |
· 파이썬에서 정규 표현식을 지원하는 re 모듈
파이썬에서는 정규 표현식을 지원하기 위해 re(Regular Expression) 모듈을 제공한다.
re 모듈은 파이썬을 설치할 때 자동으로 설치되는 내장 라이브러리 모듈이다.
re.compile는 패턴을 변수에게 치환하는 명령어이다.
· 정규식을 사용한 문자열 검색
메서드 |
목적 |
match() |
문자열의 처음부터 정규식과 매치되는지 조사한다. |
search() |
문자열 전체를 검색하여 정규식과 매치되는지 조사한다. |
findall() |
정규식과 맻되는 모든 문자열(substring)을 리스트로 돌려준다. |
finditer() |
정규식과 매치되는 모든 문자열(substring)을 반복 가능한 객체로 돌려준다. |
match, search는 정규식과 매치될 때는 match 객체를 돌려주고, 매치되지 않을 때는 None을 돌려준다.
(1) Match
<예제>
data = "aab asdfsadfb a0b 날씨가 많b이 a.b더vbc워1요a."
p = re.compile('[a-z\s]+') # 소문자 a부터 z까지와 공백을 포함하여 1개 이상만 존재하는 것만 출력
print(p.match(data))
print(p.match('max power'))
print(re.match('[가-힣\s]+', "이렇게도 가능하다."))
<re.Match object; span=(0, 15), match='aab asdfsadfb a'> <re.Match object; span=(0, 9), match='max power'> <re.Match object; span=(0, 9), match='이렇게도 가능하다'> |
<또 다른 경우의 예제>
compile 조건에 영문자 소문자만 넣어주었기 때문에 만약 문자열의 앞이 한글 또는 숫자로 시작하게 되면 다음과 같은 결과를 내놓는다.
data3 = "한글이 앞에 존재aab asdfsadfb a0b 날씨가 많b이 a.b더vbc워1요a."
p = re.compile('[a-z\s]+') # 소문자 a부터 z까지 1개 이상만
print(p.match(data3))
None |
(2) Search
data = "aab asdfsadfb a0b 날씨가 많b이 a.b더vbc워1요a."
p = re.compile('[a-z\s]+') # 소문자 a부터 z까지 1개 이상만
print(p.search(data))
<re.Match object; span=(0, 15), match='aab asdfsadfb a'> |
(3) Findall
findall은 위에서도 계속 문자를 출력할 때 자주 사용했었다.
각각의 단어를 정해준 정규식에 매치해서 리스트로 반환한다.
data3 = "한글이 앞에 존재aab asdfsadfb a0b 날씨가 많b이 a.b더vbc워1요a."
print(re.findall(r'[a-z가-힣]', data3))
<re.Match object; span=(0, 15), match='aab asdfsadfb a'> ['한', '글', '이', '앞', '에', '존', '재', 'a', 'a', 'b', 'a', 's', 'd', 'f', 's', 'a', 'd', 'f', 'b', 'a', 'b', '날', '씨', '가', '많', 'b', '이', 'a', 'b', '더', 'v', 'b', 'c', '워', '요', 'a'] |
(4) Finditer
findall과 비슷한 기능을 갖고 있다. 차이점은 반복이 가능한 객체(Iterator Object)로 반환한다는 점이다.
반복이 가능한 객체가 포함하는 각각의 요소는 match 객체이다.
data3 = "한글이 앞에 존재aab asdfsadfb a0b 날씨가 많b이 a.b더vbc워1요a."
p = re.finditer(r'[a-z가-힣0-9]', data3)
print(p)
for i in p:
print(i)
<callable_iterator object at 0x00000140A93B9DF0> <re.Match object; span=(0, 1), match='한'> <re.Match object; span=(1, 2), match='글'> <re.Match object; span=(2, 3), match='이'> <re.Match object; span=(4, 5), match='앞'> <re.Match object; span=(5, 6), match='에'> <re.Match object; span=(7, 8), match='존'> <re.Match object; span=(8, 9), match='재'> <re.Match object; span=(9, 10), match='a'> <re.Match object; span=(10, 11), match='a'> <re.Match object; span=(11, 12), match='b'> <re.Match object; span=(13, 14), match='a'> <re.Match object; span=(14, 15), match='s'> <re.Match object; span=(15, 16), match='d'> <re.Match object; span=(16, 17), match='f'> <re.Match object; span=(17, 18), match='s'> <re.Match object; span=(18, 19), match='a'> <re.Match object; span=(19, 20), match='d'> <re.Match object; span=(20, 21), match='f'> <re.Match object; span=(21, 22), match='b'> <re.Match object; span=(23, 24), match='a'> <re.Match object; span=(24, 25), match='0'> <re.Match object; span=(25, 26), match='b'> <re.Match object; span=(27, 28), match='날'> <re.Match object; span=(28, 29), match='씨'> <re.Match object; span=(29, 30), match='가'> <re.Match object; span=(31, 32), match='많'> <re.Match object; span=(32, 33), match='b'> <re.Match object; span=(33, 34), match='이'> <re.Match object; span=(35, 36), match='a'> <re.Match object; span=(37, 38), match='b'> <re.Match object; span=(38, 39), match='더'> <re.Match object; span=(39, 40), match='v'> <re.Match object; span=(40, 41), match='b'> <re.Match object; span=(41, 42), match='c'> <re.Match object; span=(42, 43), match='워'> <re.Match object; span=(43, 44), match='1'> <re.Match object; span=(44, 45), match='요'> <re.Match object; span=(45, 46), match='a'> |
'파이썬(Python)' 카테고리의 다른 글
파이썬 - 내장 함수 (0) | 2021.06.14 |
---|---|
정규 표현식(정규식) - 2 (0) | 2021.06.13 |
For 반복문 (0) | 2021.06.12 |
While문과 Random함수 (0) | 2021.06.10 |
If문 - 조건문 (0) | 2021.06.09 |