본문 바로가기
풀스택 개발 학습 과정/데이터

[데이터 수집] 정규 표현식(Regular Expression) -2

by 육츠 2023. 10. 31.
Contents 접기

re 모듈
compile() 모듈 사용하여 정규표현식 컴파일

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

 

대표적인 모듈
- match() : 문자열의 처음부터 검색하여 일치여부 판단
- search() : 문자열의 전체를 검색. 중간에라도 매치되면 결과를 반환한다
- findall() : 정규식과 매치되는 모든 문자열 리스트로 반환
- finditer() :  정규식과 매치되는 모든 문자열 튜플로 반환

# match()
m1 = p.match('python')
print(m1)
# <re.Match object; span=(0, 6), match='python'>

m3 = p.match('3 python')
print(m3)
# None

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

# findall()
p = re.compile('[a-z]+') # 하나 이상
result = p.findall('life is too short')
# ['life', 'is', 'too', 'short']

# finditer()
result = p.finditer("life is too shoort")
for m in result:
    print(m) # 여러개의 매치 객체
print(result)
# <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, 18), match='shoort'>

 

match() 대표적 객체 함수
- group() : 매치된 문자열 반환
- start() : 매치된 문자열의 시작 위치 반환
- end() : 매치된 문자열의 끝위치 반환
- span() :  시작과 끝값을 튜플로 반환

import re

p = re.compile('[a-z]+')
m = p.search('python')
print(m.group()) # 검색된 문자열 읽기
print(m.start())
print(m.end())
print(m.span()) # (처음,끝) : 튜플형태

# python
# 0
# 6
# (0, 6)

[문제] 전화번호 추출하기 다음의 전화번호 데이터에서 전화번호만 추출하는 정규표현식을 작성하세요.

phone = ['홍길동:010-1234-4678','우리집:02-555-3333']
pat = re.compile('\d{2,3}-\d{3,4}-\d{4}')

for p in phone:
    s = pat.search(p)
    print(s.group())

# for문 안에 넣는 거 놓침

 

컴파일 옵션
- DOTALL : dot(.) 에 관계없이 개행문자 \n 포함하여 모든 문자와 일치한다.
- IGNORECASE : 대소문자 관계없이 일치한다
- MULTILINE : 여러 줄의 문자에 대해 ^(문자열의 처음), $(문자열의 끝) 적용 
- VERBOSE : 정규식을 보기편하게

# re.DOTALL
p = re.compile('a.b',re.DOTALL)
m = p.match('a\nb')
print(m)
# <re.Match object; span=(0, 3), match='a\nb'>

# re.IGNORECASE
p = re.compile('[a-z]+',re.IGNORECASE)
m = p.match('pYthon')
print(m)
# <re.Match object; span=(0, 6), match='pYthon'>

# re.MULTILINE
p = re.compile('^python\s\w+',re.MULTILINE) 
# python 으로 시작하면서, 공백문자 하나 나오고, 숫자+문자 하나 나오면 

text = '''python one
life is too short
python two
you need python
python three
'''
m = p.findall(text)
print(m)
# ['python one', 'python two', 'python three']

 

+ 메타문자
- \A : 줄과 상관없이 전체 문자열 처음 하고만 일치하면 됨( MULTILINE 해당 안됨) 
- \Z : 줄과 상관없아 문자열의 끝과 일치하면 됨( MULTILINE 해당 안됨)
- \b: 백스페이스 의미. 단어 구분자로 사용하기 위해서는 r(raw string: 문자가 문자열 자체임을 알려줌)을 반드시 붙여야 함

import re

# \
m = re.search('안녕하세요\?', '여러분 안녕하세요?')
print(m)  # 안녕하세요?

# \b
p = re.compile(r'\bclass\b') 
print(p.search('no class at all')) # <re.Match object; span=(3, 8), match='class'>

p = re.compile(r'\sclass\s') 
print(p.search('no class at all')) # <re.Match object; span=(2, 9), match=' class '>

그룹핑
- group(0) : 전체 문자열 == group()
- group(1) : 첫 번째 그룹 문자열
- group(2) : 두 번째 그룹 문자열 

그룹핑에 이름 붙이기 : (?p<그룹이름>)

import re

# 1)
s = 'park 010-1234-5678'
p = re.compile('(\w+)\s+(\d+[-]\d+[-]\d+)')
m = p.search(s)
print(m.group())   # park 010-1234-5678
print(m.group(1))  # park
print(m.group(2))  # 010-1234-5678

# 2)
re.match(r'(a)(b)\1\2', 'abab') # (a)(b)\1\2 번호 부분이 재참조
# <re.Match object; span=(0, 4), match='abab'>

# # (?P<그룹 이름>)
p = re.compile('(?P<name>\w+)\s+(\d+[-]\d+[-]\d+)')
m = p.search('park 010-1111-2222') 
print(m.group('name'))  # park