#!/usr/bin/env python # coding: utf-8 # # **정규표현식 연습하기** # ## **1 잡아라 텍스트 마이닝 with 파이썬** # Regex Tutorials # In[1]: # 문장내 (도메인 주소) 부분 제거하기 string_data = """그러면서 (taken@kookmin.com) "문재인 대통령은 조국 장관 임명으로 민심을 분열시킨 책임을 엄중히 느끼고 제대로 된 개혁 작업을 추진하기를 바란다"며 "특히 검찰개혁이 사법개혁의 전체인양 호도하지 말고 근본적인 사법개혁을 고민하기를 바란다"고 강조했다. (bright@newsis.com)""" token_str = "\([A-z0-9\._+]*@[A-z]+\.(com|org|net|edu|co.kr)\)" import re re.sub(token_str, "", string_data) # In[2]: # .findall 을 사용하면 결과를 찾지 못함 # 제대로 찾지 못한 경우 re.findall(token_str, string_data) # In[3]: # .search 를 사용하면 제대로 된 결과 1개만 출력 re.search(token_str, string_data).group() # In[4]: # .finditer 를 사용하면 여러개를 찾는다 # https://stackoverflow.com/questions/8110059/python-regex-search-and-findall for match in re.finditer(token_str, string_data): print (match.group(0)) # In[5]: # 1개(+) 와 0개(*) 의 포함여부 차이 tokenizer = re.compile("a+b*") tokenizer.findall("aaaa, ccc, bbbb, aabbbb") # In[6]: # 시작조건 특정 tokenizer = re.compile("^a..") tokenizer.findall("abc, cba") # In[7]: # 일치 갯수의 특정 tokenizer = re.compile("a{2,3}b{2,3}") tokenizer.findall("aabb, aaabb, ab, aab") # ## **2 김기현의 딥러닝 자연어 분석** # Regex Tutorials # In[8]: # 객체의 치환 import re p = re.compile(r"(?P\w+)\s+(?P(\d+)[-]\d+[-]\d+)") print(p.sub("\g \g", "park 010-1234-1234")) p = re.compile(r"(?P\w+)\s+(?P(\d+)[-]\d+[-]\d+)") print(p.sub("\g<2> \g<1>", "park 010-1234-1234")) dot_to_nun = re.compile(r"(?P(\d+)).(?P(\d+))") dot_to_nun.sub("\g=\g", "1232.3124") # In[9]: import re re.findall('.+', "sales.xls, test.xls") # In[10]: re.findall('(
|
)', "
텍스트
") # In[11]: import re p = re.compile(r"(?P\w+)\s+(?P(\d+)[-]\d+[-]\d+)") print(p.sub("\g \g", "park 010-1234-1234")) # In[12]: text = "$23.24 의 가격은 $69.23 까지 상승하였습니다" p = re.compile(r"\$[0-9.]+") p.findall(text) # In[13]: p = re.compile(r"(?<=\$)[0-9.]+") p.findall(text) # # **Regex 정규식의 사용** # # ## **1 Re 모듈의 기본 사용법** # 1. **re.findall() :** 조건에 해당되는 모든 객체 추출 # 1. **re.search() :** () 그룹 검색결과 추출 # 1. **re.sub() :** 문자열 교체 # In[1]: import re def basicregex(): contactInfo = 'Doe, John: 1111-1212' line = "This is test sentence and test sentence is also a sentence." findallobj = re.findall(r'sentence', line) print (">>> re.findall() \n{}\n".format(findallobj)) groupwiseobj = re.search(r'(\w+), (\w+): (\S+)', contactInfo) print (">>> re.groups \n1st group: {}\n2nd group: {}\n3rd group: {}".format( groupwiseobj.group(1), groupwiseobj.group(2), groupwiseobj.group(3))) phone = "1111-2222-3333 # This is Phone Number" num = re.sub(r'#.*$', "", phone) print ("\n>>> re.sub()\nPhone Num : {}".format(num)) contactInforevised = re.sub(r'John', "Peter", contactInfo) print ("\n>>> Revised contactINFO : ", contactInforevised) basicregex() # ## **2 .match(), .search()** # 1. **.match() :** 문자열 **시작부분의** 일치여부 확인 # 1. **.search() :** 문자열 **아무 곳** 일치여부 확인 # In[2]: import re def searchvsmatch(): line = "I love animals."; matchObj = re.match(r'animals', line, re.M | re.I) if matchObj: print ("match: ", matchObj.group()) else: print ("No 're.match'!!") searchObj = re.search(r'animals', line, re.M | re.I) if searchObj: print ("re.search: ", searchObj.group()) else: print ("Nothing found!!") searchvsmatch() # ## **3 Re 플래그 및 사용법** # 1. 기본 플래그 : 정규식 검색시 설정값을 추가할 수 있다 # 1. [re 플래그 사용예제](https://m.blog.naver.com/PostView.nhn?blogId=happy_jhyo&logNo=70144999358&proxyReferer=https%3A%2F%2Fwww.google.com%2F) # In[3]: import re m1 = 'about = 12345 \n b = 444 \t c=100' p1 = r'([a-zA-Z]\w*)\s*=\s*(\d+)' re.findall(p1, m1) # In[4]: cp = re.compile(p1) m = re.match(cp,m1) m.groups() # m.group(1), m.group(2) # In[5]: # re.I : 대소문자 무시 m1 = 'tTh cat was hungry, they were scare because of The cat' p1 = re.compile('the') p2 = re.compile('the', re.I) r1 = re.findall(p1, m1) r2 = re.findall(p2, m1) r1, r2 # In[6]: # re.M : 각 줄마다 반복 m1 = '''tTh cat was hungry, they were scare because of The cat''' p1 = re.compile('^[a-zA-Z]\w+', re.I|re.M) r1 = re.findall(p1, m1) r1 # In[7]: # re.S : 모든 문자에 \n 등도 포함 m1 = '''tTh cat was hungry, they were scare because of The cat''' p1 = re.compile('hungry,.*they', re.I) p2 = re.compile('hungry,.*they', re.I|re.S) r1 = re.findall(p1, m1) r2 = re.findall(p2, m1) r1, r2 # In[8]: # re.X : 문자열이 아닌 문장을 정규식을 할 수 있다. s = '''\n\ntitle\n THis is bodyspam \n\n ''' p = r'''\s*.*\s*.*''' r = re.match(p, s, re.X) r.group() # ## **4 고급 레벨 정규표현식** # 1. **(?=re패턴) Positive LookAhead :** 정의된 패턴 **앞의** 문자열을 추출 # 1. **(?<=re패턴) Positive LookBehind :** 정의된 패턴 **다음의** 문자열을 추출 # 1. **(?!re패턴) Negative LookAhead :** 정의된 패턴을 **따르지 않는 앞의** 문자열을 추출 # 1. **(? {'a','e','l','p'} def known(words): return set(w for w in words if w in WORDS) known('aple'), P('able') # In[14]: # 단어 편집거리 측정함수 def edits1(word): a_z = 'abcdefghijklmnopqrstuvwxyz' splits = [(word[:i],word[i:]) for i in range(len(word)+1)] # 단어의 분리 deletes = [L+R[1:] for L,R in splits if R] # 예제1) 1개단어 없는 예 transposes = [L+R[1]+R[0]+R[2:] for L,R in splits if len(R)>1] # 예제2) 중간단어 섞인 예 replaces = [L+c+R[1:] for L,R in splits if R for c in a_z] # 예제3) a-z 1개씩 변경 예 inserts = [L+c+R for L,R in splits for c in a_z] # 예제4) a-z 1개씩 추가 예 return set(deletes+transposes+replaces+inserts) # 예제1 ~ 예제4 모두 생성 list(edits1('aple'))[:7] # In[15]: # "All edits that are two edits away from `word`." def edits2(word): return (e2 for e1 in edits1(word) for e2 in edits1(e1)) edits2('aple') # In[16]: # "Generate possible spelling corrections for word." def candidates(word): return (known([word]) or known(edits1(word)) or known(edits2(word)) or [word]) # "Most probable spelling correction for word." def correction(word): return max(candidates(word), key=P) print (correction('aple')) print (correction('correcton')) print (correction('statament')) print (correction('tutpore')) print (correction('datactive')) # 갯수는 동일하지만 철자만 다른경우 정확도 높음 # ## **6 Word Piece Model 한글실습** # - defaultDict 단어 token 을 만든 뒤, # - Bi-Gram 빈도를 기준으로 단어 Token 을 찾기 # In[17]: # 단어 Token 을 음절단위로 구분하기 data = [" ".join(list(_)+[""]) for _ in ["아버지께", "아버지를", "아버지에게", "아버지와"]] data # In[18]: data = { "아 버 지 께 ":5, "아 버 지 를 ":2, "아 버 지 에 게 ":6, "아 버 지 와 ":3, } data.values() # In[19]: from collections import defaultdict # N-Gram 생성함수 def findNagram(data): pair = defaultdict(int) for k, v in data.items(): tokens = k.split() for i in range(len(tokens)-1): pair[tuple(tokens[i:i+2])] += v return pair # maxValue 변수를 추가해 반복 횟수를 제한 합니다 def mergeNgram(maxKey, data): newData = dict() for k, v in data.items(): newKey = re.sub(" ".join(maxKey), "".join(maxKey), k) newData[newKey] = v return newData maxValue = max(data.values()) maxValue # In[20]: # 작업을 반복하며 고유한 단어를 찾습니다 for _ in range(1000): pairList = findNagram(data) maxKey = max(pairList, key=pairList.get) #print(maxKey, pairList[maxKey]) if pairList[maxKey] > maxValue: data = mergeNgram(maxKey, data) else: break print(data) pairList #

# # **손에 잡히는 정규표현식** # ## **1 문자 다루기** # In[21]: sample = """저의 이름은 벤 입니다. 홈페이지 주소는 https://www.forta.com 입니다 """ import re re.findall('홈페이지', sample) # In[22]: # '.' : 문자, 알파벳, 숫자, 문장부호 모두포함 (공백도 포함) re.findall('.', sample)[:15] # In[23]: # '..' : 공백포함 2개 단어목록을 추출 re.findall('..', sample)[:9] # In[24]: # 연산기호가 아닌 순수한 "." 을 추출합니다. re.findall('\.', sample) # In[25]: re.findall('\n', sample) # In[26]: re.findall('[A-z가-힣]*', sample)[:10] # In[27]: # '.' 을 포함한 문자 re.findall('[A-z.]+', sample) # ## **2 문자 집합으로 찾기** # Grouping # In[28]: sample = """문장에서 '정규식의 활용'을 파이썬 이외에 다양한 언어에서도 활용 가능합니다""" sample = """이번 주문은 처리가 가능합니다. 단 거주지가 서울경기도 에 제한됩니다""" # .* : 탐욕적 수량자 (조건에 포함되는 큰 덩어리를 추출) re.findall('.*', sample)[0] # In[29]: # .*? : 게으른 수량자 (조건에 포함되는 작은 덩어리들을 추출) re.findall('.*?', sample) # In[30]: sample = """고양이 는 강이지와 함께 고양이 새끼들을 키운다""" # sample = """The cat scattered his food all over the room.""" re.findall('[\b고양이\b]', sample) re.findall('고양이', sample) # In[31]: re.findall('[\bcat\b]', sample) # In[32]: sample = """ http://www.daun.net 또는 https://www.naver.com""" re.findall('https?://www.*?', sample) # In[33]: sample = """ 1999-12-11 년도의 작업이 2019-01-11 작업을 진행합니다 """ re.findall('(19|20)[0-9]+', sample) # In[34]: sample = """ 010-9999-3333 010-5555-3333 010-5554-2351""" re.sub('(\d{3})(-)(\d{3,4})(-)(\d{3,4})', '\g<0>', sample) # In[35]: # "\g<인덱스> : 앞에서 추출한 객체들을 재활용시 인덱스값 활용" re.subn('(\d{3})(-)(\d{3,4})(-)(\d{3,4})', '\g<1>:\g<3>:\g<5>', sample) # In[36]: # 객체 재활용시 "인덱스 이름"을 활용 re.subn('(?P\d{3})(-)(?P\d{3,4})(-)(?P\d{3,4})', '\g:\g:\g', sample) # In[37]: sample = """ 제목을 입력 합니다. """ re.findall('<[titleTITLE]+>.*<[/titleTITLE]+>', sample) # ## **실전 블로그 작업 시작하기** # - **식재료** 목록 (원본데이터를 그대로 활용하기) # - **식품** 목록 (한식메뉴 목록 데이터) # In[38]: sample = """ 재료: 돼지고기, 파, 양파, 호박, 양배추, 전분, 면 양념: 춘장, 식용유, 간장, 설탕 """ re.findall('된장국*?\w+', sample) # In[39]: # 파일이름 필터링 sample = "na1.xls na2.xls sa2.xls sam.xls sandwich.xls sax.xls" import re re.findall('[ns]a[^0-9]\.xls', sample)