regex 나래를 펴라!!!정규표현식을 사용해서 텍스트에 포함된 패턴을 매칭할 수 있고, 문구를 추출하는 것도 가능하고 문법에 맞춰 문장을 생성시키는 것도 가능하다.
챗봇을 개발할 때 단순한 패턴을 매칭시켜 대화가 가능한 챗봇을 개발하는 것이 가능하다. 즉 pattern에 정규 표현식을 정의하고 message에서 앞서 정규표현식으로 정의한 패턴이 있는지 파악하는 것이다.
import re
pattern = "Who is .*"
message = "Who is Albert Einstein?"
pattern_matching = re.search(pattern, message)
if pattern_matching:
print("패턴을 찾는데 성공했습니다.")패턴을 찾는데 성공했습니다.
이를 조금더 확장하면 pattern에 좀더 정교한 정규표현식을 넣게 되면 화자의 의도도 파악할 수 있게 된다. 즉, pattern에 인사와 관련된 패턴을 정규표현식으로 작성하고 이를 화자 메시지와 매칭되면 이를 통해 화자의 의도를 파악하게 된다.
pattern = "how are you\?|hello there|how is it going\?"
## 인사 -----
greeting_message = "how is it going?"
pattern_matching = re.search(pattern, greeting_message)
if pattern_matching:
print("인사")
else:
print("다시 말해 주세요!")
## 인사 -----인사
just_message = "how are you doing?"
pattern_matching = re.search(pattern, just_message)
if pattern_matching:
print("인사")
else:
print("다시 말해 주세요!")다시 말해 주세요!
ELISA 유형의 챗봇을 개발할 때 많이 사용되는 대화 패턴이 존재한다. 이러한 대화패턴은 정규표현식을 사용해서 챗팅 대화 문구를 추출해두고 추후 별도 활용한다.
pattern = "Tell me a reason why (.*)"
message = "Tell me a reason why you're inhibiting yourself."
match = re.search(pattern, message)
print(match.group(1))you're inhibiting yourself.
정규표현식으로 독립체(entity)를 추출하는 것도 가능한데 이름, 지명, 단체 등은 영어로 대문자로 흔히 표현되곤 한다. 이런 패턴을 정규표현식으로 표현하여 추출해낼 수 있다. 아래와 같이 한 단어인 경우 대문자를 첫문자로 갖는 단어를 독립체로 인식해서 추출하는 것이 가능하지만, 두단어로 독립체를 구성하는 경우에는 문제가 있는 것이 확인된다.
entity_pattern = re.compile("[A-Z]{1}[a-zA-Z]*")
another_sentence = "John is from Atlanta"
entity_pattern.findall(another_sentence)['John', 'Atlanta']
sentence = "The Software Carpentry Foundation and its sibling lesson project, Data Carpentry, have merged to become The Carpentries, a fiscally sponsored project of Community Initiatives, a 501(c)3 non-profit incorporated in the United States."
entity_pattern.findall(sentence)['The', 'Software', 'Carpentry', 'Foundation', 'Data', 'Carpentry', 'The', 'Carpentries', 'Community', 'Initiatives', 'United', 'States']
정규표현식을 사용해서 텍스트의 특정 단어를 바꾸는 것을 가볍게 다뤄보자.
sentence = "성호와 영희는 R이냐 파이썬이냐를 두고 심하게 다퉜다."
result = re.sub(r"파이썬", "Python", sentence)
print(result)성호와 영희는 R이냐 Python이냐를 두고 심하게 다퉜다.
이제 정규표현식을 활용하여 민감정보 전화번호/주민번호/이름 등을 삭제(redact)하거나 마스킹(masking)하는 것을 살펴보자.
mobile_phone = "\d{3}-\d{3,4}-\d{4}"
regular_phone = "\d{2,3}-\d{3,4}-\d{4}"
email = "(\w+\.)*\w+@(\w+\.)+[A-Za-z]+"
pattern = re.compile(mobile_phone + "|" + regular_phone + "|" + email)
pledge_message = "경찰의 내사를 받고 있는 성호군은 한OO 일보와 조0일보를 잠시 착각한 것으로 밝혀졌으며 이 와중에 전화번호 010-2345-2212 가 외부로 유출되어 핸드폰 번호를 바꾸었으나 이 과정에서 집전화번호 031-222-3234 도 유출되어 더이상 전화를 사용할 수 없는 자연인으로 돌아갔습니다. 이제 본인 전자우편 sungho@gmail.com도 당연히 외부에 절대 유출되지 않도록 국민신문고에 민원을 넣었습니다."
result = re.sub(pattern, "XXX-XXXX-XXXX", pledge_message)
print(result)경찰의 내사를 받고 있는 성호군은 한OO 일보와 조0일보를 잠시 착각한 것으로 밝혀졌으며 이 와중에 전화번호 XXX-XXXX-XXXX 가 외부로 유출되어 핸드폰 번호를 바꾸었으나 이 과정에서 집전화번호 XXX-XXXX-XXXX 도 유출되어 더이상 전화를 사용할 수 없는 자연인으로 돌아갔습니다. 이제 본인 전자우편 XXX-XXXX-XXXX도 당연히 외부에 절대 유출되지 않도록 국민신문고에 민원을 넣었습니다.
항공권을 예매하는 경우 출발지와 도착지 두가지 정보가 필요하다. 이를 정규표현식으로 잡아내기 위해서 from과 to를 각각 정의하고 패턴을 추출해서 출발지와 도착지를 추출해낸다.
sentence = "Please find me 2 roundtrip economy tickets from Chicago to London"
from_to = re.compile('.* from (.*) to (.*)')
to_from = re.compile('.* to (.*) from (.*)')
from_to_match = from_to.match(sentence)
to_from_match = to_from.match(sentence)
if from_to_match and from_to_match.groups():
_from = from_to_match.groups()[0]
_to = from_to_match.groups()[1]
print("From: {}, To: {}".format(_from, _to))
elif to_from_match and to_from_match.groups():
_to = to_from_match.groups()[0]
_from = to_from_match.groups()[1]
print("From: {}, To: {}".format(_from, _to))From: Chicago, To: London
gk_ (Jan 6, 2017), “Soul of the Machine: How Chatbots Work”↩
Usman Malik, “Using Regex for Text Manipulation in Python”, Stack Abuse↩
Sumit Raj (2019), “Building Chatbots with Python - Using Natural Language Processing and Machine Learning”↩