a* : a가 0회 이상 반복을 뜻한다. a, aa, aaaaa는 a 자체를 의미한다. [ ] 사이의 문자들과 매칭[abc] : a, b, c 중 하나의 문자와 매치-를 이용해 범위로 설정할 수 있다.[a-z] : 알파벳소문자중 하나의 문자와 매치[a-zA-Z0-9] : 알파벳대소문자와 숫자 중 하나의 문자와 매치[가-힣ㄱ-ㅎㅏ-ㅣ]: 한글중 하나와 매치[^ 패턴] : ^ 으로 시작하는 경우 반대의 의미. 와서 안되는 패턴을 의미[^abc] : a, b, c를 제외한 나머지 문자들 중 하나와 매치.[^a-z] : 알파벳 소문자를 제외한 나머지 문자들 중 하나와 매치\d : 숫자와 매치. [0-9]와 동일\D : \d의 반대. 숫자가 아닌 문자와 매치. [^0-9]와 동일\w : 문자와 숫자, (underscore)와 매치. `[a-zA-Z가-힣0-9]`와 동일 (문자는 특수문자 제외한 일반문자-언어상관없는-들을 말한다.\W : \w의 반대. 문자와 숫자와 가 아닌 문자와 매치. `[^a-zA-Z가-힣0-9]`와 동일\s : 공백문자와 매치. tab,줄바꿈,공백문자와 일치\S : \s와 반대. 공백을 제외한 문자열과 매치.\b : 단어 경계(word boundary) 표시. 단어와 단어를 구분할 수 있는 문자로 보통 공백이 많이 쓰임. 공백이외에도 ,, ., \n, | 등 문자들을 표현한다.\b가족\b => 우리 가족 만세(O), 우리가족만세 (X)\B : \b의 반대. 단어 경계로 구분된 단어가 아닌 경우\B가족\B => 우리 가족 만세(X), 우리가족만세 (O)* : 앞의 문자(패턴)과 일치하는 문자가 0개 이상인 경우. (a*b)+ : 앞의 문자(패턴)과 일치하는 문자가 1개이상인 경우. (a+b)? : 앞의 문자(패턴)과 일치하는 문자가 한개 있거나 없는 경우. (a?b){m} : 앞의 문자(패턴)가 m개. (a{3}b){m,} : 앞의 문자(패턴)이 m개 이상. (a{3,}b){m,n} : 앞의 문자(패턴)이 m개이상 n개 이하. (a{2,5}b) ., *, +, ? 등 메타문자들을 리터럴로 표현할 경우 \를 붙인다.^ 문자열의 시작 (^abc)$ : 문자열의 끝 (abc$). : 한개의 모든 문자(\n-줄바꿈 제외) (a.b)| : 둘중 하나(OR) (?:010|011|016|019)( ) : 패턴내 하위그룹을 만들때 사용 p = re.compile(r'\d+')
p.search('abc123def')re 모듈의 원하는 작업을 하는 함수를 호출한다. Argument로 패턴과 처리할 값을 전달한다.re.search(r'\d+', 'abc123def')
raw string
- 패턴문자중
\로 시작하는 것들을 사용할 경우escape문자와의 구분을 위해\\두개씩 작성해야한다. 그래서 패턴을 지정할 때는 raw string을 사용하는 것이 편리하다.
re.compile('\b가족\b'):\b를 escape 문자 b(백스페이스)로 인식re.compile(r'\b가족\b'):\b가 일반문자가 되어 컴파일시 정규식 메타문자로 처리된다.
info ='''김정수 kjs@gmail.com 801033-1010221 박영수 pys.abc@gmail.com 700121-1120212 이민영 lmy-abc@naver.com 820301-2020122 김순희 ksh@daum.net 781223-2012212 오주연 ojy@daum.net 900522-1023218 '''# Email 주소만 추출 해서 출력 email_pattern = r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?" email_list = re.findall(email_pattern, info) email_list['kjs@gmail.com',
'pys.abc@gmail.com',
'lmy-abc@naver.com',
'ksh@daum.net',
'ojy@daum.net']# 주민번호들만 조회해서 출력 jumin_pattern = r"\d{6}-?\d{7}" jumin_pattern = r"\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12][0-9]|3[01])-[1234]\d{6}" # \d{2}: 년도 숫자 두자리. # 01 ~ 09, 10, 11, 12 - (?:0[1-9]|1[0-2]) 괄호로 단순히 묶기. 0[1-9]:01~09 | or ==> 월 # (?:0[1-9]|[12][0-9]|3[01]) : 01 ~ 09, 10~19, 20~ 29, 30, 31 ## [1234]\d{6} : 0[1-9] or [12][0-9] or 3[01] jumin_list = re.findall(jumin_pattern, info) print(jumin_list)['700121-1120212', '820301-2020122', '781223-2012212', '900522-1023218']
print(info) r = re.sub(jumin_pattern, "", info) r = re.sub(jumin_pattern, "******-*******", info) print(r)김정수 kjs@gmail.com 801033-1010221
박영수 pys.abc@gmail.com 700121-1120212
이민영 lmy-abc@naver.com 820301-2020122
김순희 ksh@daum.net 781223-2012212
오주연 ojy@daum.net 900522-1023218
김정수 kjs@gmail.com 801033-1010221
박영수 pys.abc@gmail.com **-***
이민영 lmy-abc@naver.com **-***
김순희 ksh@daum.net **-***
오주연 ojy@daum.net **-***
(\d{4})/([01]\d)/([0123]\d) import re tel = "Tel: 010-1122-2121" # 전화번호: 통신사/지역번호 - 국번 - 번호 pattern = r"(\d{2,3})-(\d{3,4})-(\d{4})" # \d{2,3} : 숫자 2개 이상 3개 이하 # (1번하위그룹) - (2번하위그룹) - (3번하위그룹) p = re.compile(pattern) result = p.search(tel) # 전체 패턴을 이용해서 찾는다. if result: print(result) print("찾은 전체 문자열:", result.group(), result.group(0)) print("1번 하위 그룹-지역/통신사번호:", result.group(1)) print("2번 - 국번:", result.group(2)) print("3번 - 번호:", result.group(3)) else: print("없음")<re.Match object; span=(5, 18), match='010-1122-2121'>
찾은 전체 문자열: 010-1122-2121 010-1122-2121
1번 하위 그룹-지역/통신사번호: 010
2번 - 국번: 1122
3번 - 번호: 2121
emails = "abc@naver.com aaaa@daum.net sdkdkd@gmail.com" p = re.compile(r"(\w+)@(\w+\.\w{2,4})") e_list1 = p.findall(emails) e_list2 = p.finditer(emails) print(e_list1) for email in e_list2 : print(email.group()) print("게정:", email.group(1)) print("도메인:", email.group(2))[('abc', 'naver.com'), ('aaaa', 'daum.net'), ('sdkdkd', 'gmail.com')]
abc@naver.com
게정: abc
도메인: naver.com
aaaa@daum.net
게정: aaaa
도메인: daum.net
sdkdkd@gmail.com
게정: sdkdkd
도메인: gmail.com
\번호tels = """010-2222-3232 010-3232-3232 010-5555-5555 010-4333-1212 """ # 국번과 번호가 같은 값인 전화번호를 찾기 pattern = r"\d{2,3}-(\d{4})-\1" # 번호-(1번하위그룹)-1번하위그룹의 문자열과 같은 문자열 ## \번호 => 번호의 하위그룹과 같은 문자열 result = re.finditer(pattern, tels) for tel in result: print(tel.group(), tel.group(1)) #, tel.group(2))010-3232-3232 3232
010-5555-5555 5555
info ='''김정수 kjs@gmail.com 801033-1010221 박영수 pys.abc@gmail.com 700121-1120212 이민영 lmy-abc@naver.com 820301-2020122 김순희 ksh@daum.net 781223-2012212 오주연 ojy@daum.net 900522-1023218 ''' # 주민번호에서 뒤에 6글자를 감추기. (패턴으로 찾은 대상의 일부만 변경.) pattern = r"(\d{6}-[1234])\d{6}" # 변경하지 않을 부분을 subgroup화. result = re.sub(pattern, "\g<1>######", info) # \g<1> 1번 subgroup의 내용을 그대로 나오게 사용. ==> 찾은 문자열의 일부를 변경시 사용. print(result)김정수 kjs@gmail.com 801033-1######
박영수 pys.abc@gmail.com 700121-1######
이민영 lmy-abc@naver.com 820301-2######
김순희 ksh@daum.net 781223-2######
오주연 ojy@daum.net 900522-1######
# info에서 이메일에서 계정을 #### 감추기. p = re.compile(r"([\w\.-]+)@(\w+\.\w{2,4})") # (g1)@(g2) result = p.sub("####@\g<2>", info) print(result)김정수 ####@gmail.com 801033-1010221
박영수 ####@gmail.com 700121-1120212
이민영 ####@naver.com 820301-2020122
김순희 ####@daum.net 781223-2012212
오주연 ####@daum.net 900522-1023218
\번호 , r'(\d{3}) \1' => 중복되는 것을 패턴으로 표현할 때.\g<번호>? 붙인다.*?, +?, {m,n}?content = "<div>파이썬<b>정규표현식</b></div>입니다." # 태그들을 조회 <div><b></b></div> # result = re.findall(r"<.+>", content) result = re.findall(r"<.+?>", content) result['<div>', '<b>', '</b>', '</div>']