빅데이터 프로그래밍/Python

[Python] 23. Regular Expression(정규 표현식) 기본 문법 실습 1

밍글링글링 2017. 8. 5.
728x90
01. 정규 표현식
 
1. 정규식을 사용하지 않는 경우의 전화번호 검증
 
[실행 화면]
111-1111-1111 는 휴대폰 번호입니다.
True
02-1111-1111 는 휴대폰 번호입니다.
False
----------------------------------
전화 번호 발견: 111-1111-1111
전화 번호 발견: 222-2222-2222
처리를 종료했습니다.
  
 
▷ /reexam/re01.py
-------------------------------------------------------------------------------------
# -*- coding: utf-8 -*-

def isPhoneNumber(text):
    if len(text) != 13: # 111-1111-1111
        return False
    for i in range(0, 3): # 0 ~ 2
        if not text[i].isdecimal(): # text[0] = 1, text[1] = 1, text[2] = 1
            return False
    if text[3] != '-':
        return False
    for i in range(4, 8): # 111-1111-1111
        if not text[i].isdecimal():
            return False
        if text[8] != '-':
            return False
    for i in range(9, 13):
        if not text[i].isdecimal():
            return False
        
    return True        

if __name__ == '__main__':
    print('111-1111-1111 는 휴대폰 번호입니다.')
    print(isPhoneNumber('111-1111-1111'))
    print('02-1111-1111 는 휴대폰 번호입니다.')    
    print(isPhoneNumber('02-1111-1111'))    
    
    print('----------------------------------------')
    message="""저는 2개의 전화번호를 사용합니다. 111-1111-1111이고 부재중이면
                     222-2222-2222로 전화부탁합니다. """
    for i in range(len(message)):
        text = message[i:i+13]
        if isPhoneNumber(text):
            print('전화 번호 발견: ' + text)
            
    print('처리를 종료했습니다.')                         
    
        
    
-------------------------------------------------------------------------------------
 
 
2. 정규 표현식의 사용
- compile(): 정규식을 미리 파싱하여 메모리에 패턴 저장
- search(): 처음으로 일치하는 문자열의 Match 객체 리턴
- groups(): 일치하는 모든 문자열 산출
- group(): 일치하는 문자열의 부분 문자열 산출

 
[실행 화면]
<class '_sre.SRE_Match'>
전화 번호 발견: 000-1111-2222
--------------------------------------------
mo.group(): 000-1111-2222
mo.group(0): 000-1111-2222
mo.group(1): 000
mo.group(2): 1111
mo.group(3): 2222
mo.groups(): ('000', '1111', '2222')
--------------------------------------------
telecom: 000
num1: 1111
num2: 2222
--------------------------------------------
telecom: (000)
num1: 1111-2222
 
 
▷ /reexam/re02.py
-------------------------------------------------------------------------------------
# -*- coding: utf-8 -*-

import re

if __name__ == '__main__':
    phoneNumRegex = re.compile(r'\d\d\d-\d\d\d\d-\d\d\d\d')
    mo = phoneNumRegex.search('나의 전화번호는 000-1111-2222  입니다.')
    print(type(mo))
    print('전화 번호 발견: ' + mo.group())
    print('--------------------------------------------')
    # ()는 정규식을 그룹으로 묶어서 처리하는 경우 선언
    phoneNumRegex = re.compile(r'(\d\d\d)-(\d\d\d\d)-(\d\d\d\d)')
    mo = phoneNumRegex.search('나의 전화번호는 000-1111-2222  입니다.')
    print('mo.group(): ' + mo.group())
    print('mo.group(0): ' + mo.group(0)) # 전체 문자열
    print('mo.group(1): ' + mo.group(1)) # 1 그룹
    print('mo.group(2): ' + mo.group(2)) # 2 그룹
    print('mo.group(3): ' + mo.group(3)) # 3 그룹
    print('mo.groups(): ' + str(mo.groups()))  # tuple
    print('--------------------------------------------')
    telecom, num1, num2 = mo.groups() # tuple에서 3개의 값을 동시추출
    print('telecom: ' + telecom)
    print('num1: ' + num1)
    print('num2: ' + num2)
    print('--------------------------------------------')
    phoneNumRegex = re.compile(r'(\(\d\d\d\)) (\d\d\d\d-\d\d\d\d)')
    mo = phoneNumRegex.search('나의 전화번호는 (000) 1111-2222  입니다.') 
    print('telecom: ' + mo.group(1))
    print('num1: ' + mo.group(2))

-------------------------------------------------------------------------------------
 
 
3. 선택, 물음표와 선택적 대조, 별표로 0개 또는 그 이상과 일치시키기
- ?: 그 앞에 있는 그룹이 0번또는 1번만 선택적으로 등장해야함.
- *: 0개 또는 그 이상과 일치하는 경우
- +: 적어도 1번 이상 일치하는 경우

[실행 화면]

Batman
Tina Fey
--------------------------------------------
Batmobile
mobile
--------------------------------------------
Batman
Batwoman
--------------------------------------------
000-1111-2222
1111-2222
--------------------------------------------
일치하지 않음
Batwoman
Batwowowoman
 
▷ /reexam/re03.py
-------------------------------------------------------------------------------------
# -*- coding: utf-8 -*-

import re

if __name__ == '__main__':
    heroRegex = re.compile(r'Batman|Tina Fey')
    # 첫번째 대응된 문자열 추출
    mo = heroRegex.search('Batman and Tina Fey.')
    print(mo.group())
    mo = heroRegex.search('Tina Fey and Batman and')
    print(mo.group())    
    print('--------------------------------------------')
    batRegex = re.compile(r'Bat(man|mobile|copter|bat)')
    mo = batRegex.search('Batmobile lost a wheel')
    print(mo.group())   # 전체 일치  
    print(mo.group(1)) # 부분 일치
    print('--------------------------------------------')
    batRegex = re.compile(r'Bat(wo)?man') # ?앞 문자 wo는 선택적임.
    mo = batRegex.search('The Adventures of Batman')
    if mo != None:
        print(mo.group())
    mo = batRegex.search('The Adventures of Batwoman')
    print(mo.group())
    print('--------------------------------------------')
    phoneRegex = re.compile(r'(\d\d\d-)?\d\d\d\d-\d\d\d\d')
    mo = phoneRegex.search('나의 전화번호는 000-1111-2222  입니다.')
    print(mo.group())
    mo = phoneRegex.search('나의 전화번호는 1111-2222  입니다.')
    print(mo.group())
    print('--------------------------------------------')
    batRegex = re.compile(r'Bat(wo)+man') # *앞 문자 1번이상 무제한 등장
    mo = batRegex.search('The Adventures of Batman')
    if mo != None:
        print(mo.group())
    else:
        print('일치하지 않음') 
           
    mo = batRegex.search('The Adventures of Batwoman')
    print(mo.group())
    mo = batRegex.search('The Adventures of Batwowowoman')
    print(mo.group())

-------------------------------------------------------------------------------------
 
4. 특정 횟수의 반복, 최소, 최대 일치
- {3}: 문자열이 3번 등장해야함.
- {3, 5}: 문자열이 3 ~ 5번 등장해야함.
- findall(): 문자열의 list를 리턴함, 그룹이 있으면 tuple의 list를 리턴함.

[실행 화면]

HaHaHa
True
--------------------------------------------
HaHaHaHaHa
HaHaHa
--------------------------------------------
['000-1111-2222', '111-2222-3333']
--------------------------------------------
[('000', '1111', '2222'), ('111', '2222', '3333')]
 
▷ /reexam/re04.py
-------------------------------------------------------------------------------------
# -*- coding: utf-8 -*-

import re

if __name__ == '__main__':
    haRegex = re.compile(r'(Ha){3}')
    mo = haRegex.search('HaHaHa')
    print(mo.group())
    mo = haRegex.search('HaHa')
    print(mo == None) # True
    print('--------------------------------------------')
    haRegex = re.compile(r'(Ha){3,5}')  # 최대 일치 문자열 우선
    mo = haRegex.search('HaHaHaHaHa')
    print(mo.group())
    haRegex = re.compile(r'(Ha){3,5}?') # 최소 일치 문자열 우선
    mo = haRegex.search('HaHaHaHaHa')
    print(mo.group()) # HaHaHa   
    print('--------------------------------------------')
    phoneNumRegex = re.compile(r'\d\d\d-\d\d\d\d-\d\d\d\d')
    mo = phoneNumRegex.findall('나의 전화번호는 000-1111-2222  111-2222-3333 입니다.')
    print(mo)  # ['000-1111-2222', '111-2222-3333'] list
    print('--------------------------------------------')
    phoneNumRegex = re.compile(r'(\d\d\d)-(\d\d\d\d)-(\d\d\d\d)')
    mo = phoneNumRegex.findall('나의 전화번호는 000-1111-2222  111-2222-3333 입니다.')
    # 정규표현식이 group을 사용하면 tuple로 전환하여 list로 리턴
    # [('000', '1111', '2222'), ('111', '2222', '3333')]
    print(mo)
    
    
-------------------------------------------------------------------------------------
 
 
5. 문자 대응
- \d: 0 ~ 9 숫자
- \D: 숫자외의 모든 문자
- \w: 문자, 숫자, 언더바로 보통 단어와 일치
- \W: 문자, 숫자, 언더바외의 모든 문자
- \s: 빈칸, 탭, 줄바꿈 문자로 보통 공백과 일치
- \S: 빈칸, 탭, 줄바꿈 문자외의 모든 문자
- [abcdeABCDE]: 사용자 정의 문자 클래스의 선언, 일치하는 문자의 검색
- [0-5].: 0. ~ 5.과 일치하는 문자
- [^abcdeABCDE]: ^(캐럿)은 일치하지 않는 문자의 검색
- ^Hello: Hello로 시작하는 문자열
- Hello$: Hello로 끝나는 문자열
- ^Hello$: 정확히 문자열이 Hello와 일치해야함.
- \d$: 숫자로 끝나는 문자열
- ^\d+$: 하나 이상의 숫자로 시작하고 끝나는 문자열

[실행 화면]

['1 january', '2 February', '3 March']
--------------------------------------------
['a', 'a', 'e', 'b', 'a', 'a', 'c']
--------------------------------------------
['1', ' ', 'j', 'n', 'u', 'r', 'y', ',', ' ', '2', ' ', 'F', 'r', 'u', 'r', 'y', ',', ' ', '3', ' ', 'M', 'r', 'h']
--------------------------------------------
<class '_sre.SRE_Match'>
Hello
True
--------------------------------------------
<class '_sre.SRE_Match'>
7
True
--------------------------------------------
<class '_sre.SRE_Match'>
2017
True
--------------------------------------------
   
 
▷ /reexam/re05.py
-------------------------------------------------------------------------------------
# -*- coding: utf-8 -*-

import re

if __name__ == '__main__':
    monthRe = re.compile(r'\d+\s\w+')
    mo = monthRe.findall('1 january, 2 February, 3 March')
    print(mo)  # ['1 january', '2 February', '3 March']
    print('--------------------------------------------')
    monthRe = re.compile(r'[abcdeABCDE]') # 독립 문자 선언
    mo = monthRe.findall('1 january, 2 February, 3 March')
    print(mo)  # ['a', 'a', 'e', 'b', 'a', 'a', 'c']
    print('--------------------------------------------')
    monthRe = re.compile(r'[^abcdeABCDE]') # 매칭 안됨
    mo = monthRe.findall('1 january, 2 February, 3 March')
    print(mo)  # ['1', ' ', 'j', 'n', 'u', 'r', 'y', ',', ' 
    print('--------------------------------------------') 
    reg = re.compile(r'Hello')
    regre = reg.search('Hello python')
    print(type(regre))
    print(regre.group()) # Hello
    print(reg.search('hello python') == None) # 못찾은 경우
    print('--------------------------------------------') 
    reg = re.compile(r'\d$')
    regre = reg.search('start 2017')
    print(type(regre))
    print(regre.group()) # 7
    print(reg.search('2017 start') == None) # True
    print('--------------------------------------------')     
    reg = re.compile(r'^\d+$')
    regre = reg.search('2017')
    print(type(regre))
    print(regre.group()) # 2017
    print(reg.search('2017 start') == None) # True
    print('--------------------------------------------')    
    
    
    
-------------------------------------------------------------------------------------
 

728x90

댓글