파이썬(Python)

정규 표현식(정규식) - 1

BlueNoa 2021. 6. 13. 05:21
728x90
반응형

· 정규 표현식

정규 표현식 또는 정규식은 대량의 문자열에서 특정 문자열을 추출하거나 특정 단어를 확인하거나 원하는 문자열을 참조, 수정 등을 할 때 사용하며 입력자료의 오류 검사 등을 하기 위한 기법이다. 

이는 파이썬에서만 사용되는 것이 아니라 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'>

 

 

 

728x90
반응형

'파이썬(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