正则表达式:学习总结
正则表达式
Resources:
The Missing semester 第四讲:https://missing-semester-cn.github.io/2020/data-wrangling/
https://www.runoob.com/w3cnote/regular-expression-30-minutes-tutorial.html
简介:
正则表达式是一种文本模式,包括普通字符(例如,a到z之间的字母)和特殊字符(称为”元字符“),可以用来描述和匹配字符串的特定模式。正则表达式是一种用于模式匹配和搜索文本的工具,提供了一种灵活且强大的方式来查找、替换、验证和提取文本数据,并可以应用于各种编程语言和文本处理工具中,如JavaScript、Python、Java、Perl等。
实例:
正则表达式可以用某种格式来匹配所需要的字符串,在一般的匹配模式中,分为普通字符和元字符。普通字符将会根据字面意义来执行匹配,如在正则表达式中单独写入的a将匹配一般字符串中的a。而对于元字符,则具有特殊的含义,部分元字符的含义与应用如下所示:
1 | \d 匹配任意Digit的字符,也即[0-9]的匹配 |
字符框:
1 | [ ] : 匹配括号内的任意一个字符,可以用-来表示一定ascii值范围所对应的字符,如[a-z]对应所有的小写字符,同理,下面取反也可以作用于某一范围指定的字符 |
多个字符索要支持的范围,只需要多写一些到括号内即可。
如:
1 | [a-zA-Z0-9] 即可匹配所有小写、大写字母以及0-9的数字 |
字符边界:
1 | ^ : 匹配字符串的开头 |
匹配量词:
为了满足匹配各类字符串的需要,对于匹配的模式,正则表达式会通过一系列量词来完成约束。如:
1 | * 代表匹配前面的模式0次或多次 |
假设我们要匹配一个任意长度的仅有小写字母包括的字符串,我们可以这样写:
1 | patt= ^[a-z]*$ |
上面的模式中,字符^和$是锚定符,分别对应正则表达式匹配模式的起点和终点。注意,量词*一般放在对应限制字符的后面,如上述匹配语句中, *在[a-z]后,代表按照0个或无数个小写字符的字符串执行匹配。
1 | + 代表匹配前面的模式1次或多次 |
+和*是类似的,只不过+表示至少匹配一次对应的模式,也即小写字符的字符串长度至少为1。
1 | ? 代表匹配前面的模式0次或1次 |
?和之前的匹配量词*和+的区别在于,后两个量词的匹配是“贪婪的”,也即会最大化匹配的次数,将字符串中所有符合匹配条件的内容全部找出来,而?仅仅会这样做一遍,只会匹配第一个找到的符合模式的字符串结构。
1 | {n} 匹配前面的模式恰好n次(=n) |
以下是一些匹配模式重复的例子:
1 | a{3} 连续匹配三个重复的a |
这里,有一个比较奇怪的例子,例如RegexOne的第一个Lesson里,给出:
1 | abcdef |
我们使用如下的模式:
1 | ^[abc]+[a-z]{1,3}$ |
可以完成所有的匹配,也即上述正则表达式可以匹配上字符串”abc”,这说明,正则表达式中+的匹配逻辑并不完全是贪心的。若是贪心的,则abc字符串会先与[abc]+这部分匹配上,后面没有字符的话,就无法与后方[a-z]{1,3}的约束相匹配了,这说明正则表达式的匹配是全局最优的。在尽可能保证能得到匹配的情况下,实现贪心的匹配。
捕获组:
正则表达式允许我们不光匹配文本,而且从文本中提取对应信息,用以进一步的处理。这一步是通过定义字符组并使用特殊的元字符括号()来实现的。任何一对括号内维护的子模式都会被作为组来捕获,在实际应用中,这种方式可以用来从各种数据中提取手机号码,以及电子邮箱信息。
假设我们正在通过一种命令行工具,列出云端服务器中所拥有的照片文件,如我们可以使用
1 | ^(IMG\d+\.png)$ |
来捕获图片文件,并且提取全部的文件名。但是如果你只想要捕获文件名,而忽略后缀扩展名,那么我们只需要利用如下的捕获组:
1 | ^(IMG\d+)\.png$ |
即可捕获在period英文句号之前的图像文件名。
1 | ( ): 用于分组和捕获子表达式 |
对于复杂的数据,我们可能会进行信息的多层提取,这种诉求可以被嵌套分组捕获来实现。具体的,捕获组的结果是按照他们被定义的顺序来呈现的。
接上例,假设我们从一个列表中捕获所有的图像文件的文件名,若这些照片的名称都有某个数字编号,如IMG197.png,则在捕获名称的同时,我们可以用嵌套的方式来获得照片的编号。
1 | ^(IMG(\d+))\.png$ |
注意,嵌套分组是从左往右被顺序解析的,而第一个捕获组的内容,就对应着第一对括号内包含的内容。
除了捕获之外,括号还可以用来进行分组,内容就会按照分组的方式来进行匹配,如:
1 | ^I\slove\s(cats|dogs)$ |
将会匹配文本:I love cats 或I love dogs,这里括号内使用了|或逻辑来链接两种不同的模式。
返回引用:
在捕获组中收获的格式内容在许多系统中可以用\0, \1的方式来进行引用。如\0通常表示整个匹配的文本内容,\1则表示第一个捕获组所捕获的内容,\2…以此类推即可。
RegexOne练习内容:
1 | L1: ^abc[a-z]*$ |
注意,在需要控制捕获组的个数的时候,可以用?在捕获组后加上修饰,这样在没有该捕获组内容的时候,该捕获组就不会出现在返回引用的内容中。