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”↩