<jupyter_start><jupyter_text>정규 표현식(Regular Expression)  - [Regular Expresion online for PYthon] https://regex101.com  - 기계학습에서 데이타 전처리라는 골치아프고 시간이 많이 소요는 과정을 거칩니다.  - 특히, 텍스트 전처리의 경우 정규표현식을 활용하면 많은 시간낭비를 줄일 수 있습니다.  - 다음에 정리한 것은 wikidoc.net 책자에서 정리한 것입니다.  - 정규표현식을 완전히 익히고 잘 다루려면 많은 연습이 필요합니다.  - 그래서 이 연습을 하기 위한 기본 1장 1절을 정리한 것이나 아주 유용합니다.  - 간단하지만 시간이 지나면 바로 잊어버리는 것이 정규표현식입니다.  - 시간이 날때마다 지속적으로 또는 주기적으로 들어와 기본을 익히시기 바랍니다.  - 그러면 어느 순간 정규표현식을 아주 자유롭게 다룰 수 있습니다.  - 그 날이 올때까지 보고 또 보고 심심할 때마다 응용하는 연습을 하시기 바랍니다.----<jupyter_code>import re             # 정규 표현식 모듈 re<jupyter_output><empty_output><jupyter_text>---- 1) . 기호   - .은 한 개의 임의의 문자를 나타냄<jupyter_code>r = re.compile("a.c") # a와 c 사이에는 어떤 1개의 문자라도 올 수 있다. 
r.search("kkk")       # 아무런 결과도 출력되지 않는다.
r.search("abc")<jupyter_output><empty_output><jupyter_text>---- 2) ? 기호  - ?는 ? 앞의 문자가 존재할 수도 있고, 존재하지 않을 수도 있는 경우 표현<jupyter_code>r = re.compile("ab?c")   # b는 있다고 취급할 수도 있고, 없다고 취급 할 수도
r.search("abbc")         # 아무런 결과도 출력되지 않는다.
print(r.search("abc"))
  # b가 있는 것으로 판단하여 abc를 매치
print(r.search("ac")) 
print(r.search("bc"))   # b가 없는 것으로 판단하여 ac를 매치
re.search("ab?c", "abc") # 미리 컴파일하지 않고 그때 그때(속도 느림)<jupyter_output><empty_output><jupyter_text>---- 3) * 기호  - *은 바로 앞의 문자가 0개 이상일 경우를 표현<jupyter_code>r = re.compile("ab*c")
r.search("a")              # 아무런 결과도 출력되지 않는다.
print(r.search("ac")) 
     # b가 0 개
print(r.search("abc")) 
    # b가 1 개
print(r.search("abbbbc"))  # b가 4 개<jupyter_output><re.Match object; span=(0, 6), match='abbbbc'><jupyter_text>4) + 기호  - +은 바로 앞의 문자가 1개 이상일 경우를 표현<jupyter_code>r = re.compile("ab+c")
r.search("ac")            # 아무런 결과도 출력되지 않는다.
print(r.search("abc"))     # b가 1 개
print(r.search("abbbbc"))  # b가 4 개<jupyter_output><re.Match object; span=(0, 3), match='abc'>
<re.Match object; span=(0, 6), match='abbbbc'><jupyter_text>---- 5) ^ 기호  - ^는 시작되는 글자를 지정<jupyter_code>r = re.compile("^a")
r.search("bbc")            # 아무런 결과도 출력되지 않는다.
r.search("ab")             # a로 시작되는 문자열만을 찾아냅니다.<jupyter_output><empty_output><jupyter_text>---- 6) {숫자} 기호  - 문자에 해당 기호를 붙이면, 해당 문자를 숫자만큼 반복한 것을 표현<jupyter_code># a와 c 사이에 b가 존재하면서 b가 2개인 문자열에 대해서 매치
r = re.compile("ab{2}c")

r.search("ac")              # 아무런 결과도 출력되지 않는다.
r.search("abc")             # 아무런 결과도 출력되지 않는다.
print(r.search("abbc"))     # b기 정확하게 2개 나오면 메치
print(r.search("abbbbbc"))  # 아무런 결과도 출력되지 않는다<jupyter_output><re.Match object; span=(0, 4), match='abbc'>
None<jupyter_text>---- 7)  {숫자1, 숫자2} 기호  - 해당 문자를 숫자1 이상 숫자2 이하만큼 반복하면 매치<jupyter_code>r = re.compile("ab{2,8}c")

r.search("ac")            # 아무런 결과도 출력되지 않는다.
r.search("ac")            # 아무런 결과도 출력되지 않는다.
r.search("abc")           # 아무런 결과도 출력되지 않는다.
print(r.search("abbc"))        # b가 2개
print(r.search("abbbbbbbbc"))  # b가 8개
r.search("abbbbbbbbbc") # 아무런 결과도 출력되지 않는다.<jupyter_output><empty_output><jupyter_text>---- 8)  {숫자1,} 기호  - 해당 문자를 숫자1 이상 만큼 반복하면 매치<jupyter_code>r=re.compile("a{2,}bc")

r.search("bc") # 아무런 결과도 출력되지 않는다.
r.search("aa") # 아무런 결과도 출력되지 않는다.
print(r.search("aabc"))         # a가 2개 이어서 bc 매치
print(r.search("aaaaaaaabc"))   # a가 8개 이어서 bc 매치<jupyter_output><re.Match object; span=(0, 4), match='aabc'>
<re.Match object; span=(0, 10), match='aaaaaaaabc'><jupyter_text>---- 9)  [ ] 기호  - [ ]안에 문자들을 넣으면 그 문자들 중 한 개의 문자와 매치라는 의미<jupyter_code>r  = re.compile("[abc]")    # [abc]는 [a-c]와 같다.
r.search("zzz")             # 아무런 결과도 출력되지 않는다.
print(r.search("a"))
print(r.search("aaaaaaa"))
print(r.search("baac"))
print(r.search("cbaa"))
print(r.search("aBC"))
print(r.search("111"))       # 아무런 결과도 출력되지 않는다.<jupyter_output><re.Match object; span=(0, 1), match='a'>
<re.Match object; span=(0, 1), match='a'>
<re.Match object; span=(0, 1), match='b'>
<re.Match object; span=(0, 1), match='c'>
<re.Match object; span=(0, 1), match='a'>
None<jupyter_text>---- 10)  [^문자] 기호  - [^문자]는 5)에서 설명한 ^와는 완전히 다른 의미  - 여기서는 ^ 기호 뒤에 붙은 문자들을 제외한 모든 문자를 매치<jupyter_code># a 또는 b 또는 c가 들어간 문자열을 제외한 모든 문자열을 매치합니다.
r = re.compile("[^abc]")

r.search("a")  # 아무런 결과도 출력되지 않는다.
r.search("ab") # 아무런 결과도 출력되지 않는다.
r.search("b")  # 아무런 결과도 출력되지 않는다.
print(r.search("d"))
print(r.search("1"))
print(r.search("X") )<jupyter_output><re.Match object; span=(0, 1), match='d'>
<re.Match object; span=(0, 1), match='1'>
<re.Match object; span=(0, 1), match='X'><jupyter_text>____  정규 표현식 모듈 함수 예제----  (1)  re.match() 와 re.search()의 차이  - search()가 정규 표현식 전체에 대해서 문자열이 매치하는지를 본다면, match()는 문자열의 첫 부분부터 정규 표현식과 매치하는지를 확인합니다.   - 문자열 중간에 찾을 패턴이 있다고 하더라도, match 함수는 문자열의 시작에서 패턴이 일치하지 않으면 찾지 않습니다.<jupyter_code>import re
r = re.compile("ab.")
r.search("kkkabc")  
r.match("kkkabc")  #아무런 결과도 출력되지 않는다.
r.match("abckkk")<jupyter_output><empty_output><jupyter_text>---- (2)  re.split()  - split() 함수는 입력된 정규 표현식을 기준으로 문자열들을 분리하여 리스트로 리턴합니다.   - 자연어 처리에 있어서 가장 많이 사용되는 정규 표현식 함수 중 하나인데, 토큰화에 유용하게 쓰일 수 있기 때문입니다. https://docs.python.org/ko/3/library/re.html<jupyter_code>import re

text = "사과 딸기 수박 메론 바나나"
re.split(" ",text)  # text.split()
text
text.split()
text = \
"""
사과
딸기
수박
메론
바나나
"""

re.split("\n",text)
text.split('\n')
text = "사과+딸기+수박+메론+바나나"

re.split("\+",text) 
text.split('+')<jupyter_output><empty_output><jupyter_text>---- (3)  re.findall()  - findall() 함수는 정규 표현식과 매치되는 모든 문자열들을 리스트로 리턴합니다.   - 단, 매치되는 문자열이 없다면 빈 리스트를 리턴합니다.<jupyter_code>import re

text = """이름 : 김철수
전화번호 : 010 - 1234 - 1234
나이 : 30
성별 : 남"""

re.findall("\d+",text)
re.findall("\d+", "문자열입니다.") # 빈 리스트를 리턴한다.<jupyter_output><empty_output><jupyter_text>---- (4)  re.sub()  - sub() 함수는 정규 표현식 패턴과 일치하는 문자열을 찾아 다른 문자열로 대체할 수 있습니다.<jupyter_code>import re

text = "Regular expression : A regular expression, regex or regexp[1] (sometimes called a rational expression)[2][3] is, in theoretical computer science and formal language theory, a sequence of characters that define a search pattern."

re.sub('[^a-zA-Z]',' ',text)
p = re.compile("(내|나의|네꺼)")

p.sub("그의", "나의 물건에 손대지 마시오.")
# 나의 ==> 그의  로 대치되는 재미있는 sub<jupyter_output><empty_output><jupyter_text>----  정규 표현식 텍스트 전처리 예제<jupyter_code>import re  

text = """100 John    PROF
101 James   STUD
102 Mac   STUD"""  

re.split('\s+', text)
re.findall('\d+',text)   # 최소 1개 이상의 숫자 추출
re.findall('[A-Z]{4}',text) # 대문자가 연속적으로 4번 등장하는 경우
re.findall('[A-Z][a-z]+',text) # 첫번째 대문자 다음은 소문자 추출
# 아래 코드는 영문자가 아닌 문자는 전부 공백으로 치환합니다.
letters_only = re.sub('[^a-zA-Z]', ' ', text)
letters_only
letters_only.split() # convert from str to list
text = """신 의원은 “기상예보의 정확도는 담당자의 전문성에 비례한다”며 “기상관측 직원들의 교육과 훈련을 강화해야 한다”고 말했다.
사지원 기자 <EMAIL>"""

print(text)
import re

# 기사에서 기자의 email 주소 삭제
re.sub("[0-9a-zA-Z_\+]+@[a-z]+\.com", '', text)<jupyter_output><empty_output><jupyter_text>----  정규 표현식을 이용한 토큰화  - NLTK에서는 정규 표현식을 사용해서 단어 토큰화를 수행하는 RegexpTokenizer를 지원합니다.   - RegexpTokenizer()에서 괄호 안에 원하는 정규 표현식을 넣어서 토큰화를 수행하는 것입니다.<jupyter_code>import nltk
from nltk.tokenize import RegexpTokenizer

text = "Don't be fooled by the dark sounding name, <NAME>'s Orphanage is as cheery as cheery goes for a pastry shop"
print(text)

tokenizer=RegexpTokenizer("[\w]+")
print(tokenizer.tokenize(text))

import nltk
from nltk.tokenize import RegexpTokenizer

tokenizer=RegexpTokenizer("[\s]+", gaps=True)
print(tokenizer.tokenize(text))
tokenizer=RegexpTokenizer("[\s]+", gaps=False)
print(tokenizer.tokenize(text))<jupyter_output><empty_output>
StarcoderdataJupyterStructuredCleanDedup