[自然语言处理基础] Regular Expression (I): 「Ctrl + F」立马找出关键字

关键字搜寻与自然语言处理的关联

在正式介绍标题所提到的regular expression之前,我们先来聊聊为什麽搜寻关键字与自然语言处理有关。在浏览网页时,我们会习惯性地「Ctrl+F」下指令(这是在Windows作业系统,若是在MacOS则使用「⌘+F」)然後输入我们想要搜寻的关键字来找到目标。你或许会问,是什麽神奇的机制让我们得以在成百上千的字海中不费吹灰立就能定位目标字词呢?正则表达式(regular expression, RegEx)就是推动快捷搜寻的核心!
昨天我们提到在自然语言处理的一般流程当中,我们从原始文本或语料库获取资料,但其往往夹杂对於文义毫无意义的字符(如下图中的字句带有HTML标签 <s>和</s>等)。这时我们就需要先将字句进行文本清理(text cleaning)与前处理(pre-processing),才能进行下一步的特徵提取,而正则表达式正好协助我们进行资料清理!

Sketch Engine语料库中关於Covid-19的词条使用排行
图片来源:https://www.sketchengine.eu/corpora-and-languages/english-text-corpora/

什麽是正则表达式

在维基百科中,正则表达式是这麽被定义的:

A regular expression is a sequence of characters that specifies a search pattern. Usually such patterns are used by string-searching algorithms for "find" or "find and replace" operations on strings, or for input validation. It is a technique developed in theoretical computer science and formal language theory.

也就是说它是由特定字符所构成,被用来搜寻符合其指定规则的其他字串。在很多程序语言中(如C++、Perl、Python)都能够利用正则表达式来进行字串的描述与比对。

正则表达式字符与其意涵
资料来源:Computational Melody Analysis by Klaus Frieler

如何搜寻关键字

我们以Python来说明RegEx如何比对字串。首先引入Python标准函示库中的模组re

import re

我们可以透过字面常数(literal)表示符合特定规则的模式(pattern),例如我们想要在段落里找出所有为Musk或Trump的文字,可以使用 re.findall(pattern, text) 函式来进行比对:

text = \
"Tesla doesn't have a press office. Its CEO, Elon Musk, says the company doesn't need one. Instead, in a similar way to Donald Trump, he uses Twitter rather than press releases to communicate."

# Finds every word that is either "Musk" or "Trump"
found = re.findall(r"Musk|Trump", text)
print(found) # ['Musk', 'Trump']

pattern可被理解成模板,所有text当中与之吻合的字串(字串text的不重叠子字串)都都会被收录在列表(list)当中。值得注意的是,pattern以r"Regular_Expression"来表示,其中使用了前缀r表示原始字串(raw string)。而上述的正则表达式使用了 | 来表示替代(alternation),相当於逻辑符号中的OR。
(在正则表达式运算模组re中还定义了其他用来搜寻关键字的函式,如 re.match()re.search() 都有各自的用法及含意,而本篇着重在正则表达式的初步描述,就不特别一一介绍了。)

我们可以用 ^ 来比对字串的开头、用 $ 来比对结尾、也可以混用,这时候不妨加入括号 ( ) 以作为个别运算的单位:

print(re.findall(r"^Tes", text)) # ['Tes']
print(re.findall(r"cate.$", text)) # ['cate.']
print(re.findall(r"^(Tesla|Musk|Trump)", text)) # ['Tesla']
print(re.findall(r"(communicate|communicate.)$", text)) # ['communicate.']

在英文中,美英两国习惯的拼写方法不尽相同,如 honor v.s. honourrealize v.s. realisecatalog v.s. catalogue 等等,我们可以由以下问题进行pattern的设计:

Q: 是否含有 honorhonour,连同开头大小写一并考虑?
A: 将 ? (optional quantifier)加在计算字符 u 之後,表示有无含 u 皆符合(只出现一次或未出现),再将所有符合的字元 Hh并非字串)写入[ ](character set)。
程序码及执行结果如下:

text = "On my honor, I will be there."

# Searches for "honor" or "honour"
# starting with a capital or lowercase letter
print(re.findall(r"[Hh]onou?r", text)) # ['honor']

时常在歌词里我们可以看见重复出现的字母:

Ohhhhhhh woahhhhhh When will you realize baby you're worth it Don't have to do anything to earn it. Baby you're perfect You deserve it ... ot something to say. Ohhhhhhh woahhhhhh When will you realize baby you're worth it Don't have to do anything to earn it. Baby you're perfect You deserve it ... ot something to say. Ohhhhhhh woahhhhhh When will you realize b

歌词来源:You're Worth It - Cimorelli

若我们想要抓出所有充满叠字的状声词,可以使出 { } (fixed quantifier)。先选定重复出现的字符 \w (代指所有大小写英文字母、阿拉伯数字0到9以及底线 _ 的字元,其表达式也可以记为 [A-Za-z0-9_]),再指定其重复次数( {min,} : 至少出现 min 次、 {,Max} :最多出现 Max 次、 {min,Max} :介於两者之间)来设计pattern:

lyrics = \
"Ohhhhhhh woahhhhhh When will you realize baby you're worth it Don't have to do anything to earn it. Baby you're perfect You deserve it ... ot something to say. Ohhhhhhh woahhhhhh When will you realize baby you're worth it Don't have to do anything to earn it. Baby you're perfect You deserve it ... ot something to say. Ohhhhhhh woahhhhhh When will you realize b"

print(re.findall(r"\w{1,3}h{3,}", lyrics)) # ['Ohhhhhhh', 'woahhhhhh', 'Ohhhhhhh', 'woahhhhhh', 'Ohhhhhhh', 'woahhhhhh']

有没有开始感受到正则表达式的魔力了呢?关於正则表达式的基本概念就先写到这里,明天继续努力!

阅读更多

  1. Sketch Enginge语料库(依类别)

<<:  day10 : 追踪服务

>>:  案例:在AWS上透过SageMaker跟CodePipeline驾驭MLOps的参考架构(上)

Day 18-更改 state 有其风险,State manipulation 有赚有赔(?),更改前应详阅官方文件说明书

更改 state 有其风险,State manipulation 有赚有赔(?),更改前应详阅官方文...

[DAY 19] 卡多利亚良食故事馆

卡多利亚良食故事馆 地点:台南市後壁区42-27号 时间:9:00~17:00 对於一个研替来说 最...

Day 22 - Memorized Hook: useMemo

...> 如果有错误,欢迎留言指教~ Q_Q 没写完啦 useMemo 回传一个 memoi...

[day4] 安全签章 - 产生订单 & 签章(Sign)

准备讯息文本 依照参数说明,建立订单的资料结构(DAY3-参考),详细参数规格可以在永丰API技术规...

Android Studio - LOG

安卓有五种LOG的方式 搭配logcat 标记出你想知道的讯息 可以提升侦错的效率和优化程序码 Lo...