正则表达式是文本处理的利器。它的主要功能是匹配字符串。从Excel处理数据分析,甚至一个搜索框,都离不开正则表达式的使用。
不过呢,正则表达式是学习编程的一大痛点。大量的规则难以记忆,如果遇到一个大段的表达式,更像天书一样的无法阅读。常学常忘,常忘常学。有时候爬爬虾自以为学明白了、学透彻了,结果十天半个月,回来一看:"哎,你你...你谁啊?"
本期视频是一个逃课攻略。我们来借助一些现代化的工具,零基础快速上手掌握正则表达式,还不需要任何死记硬背。
我要推荐的第一个工具是这个网站:
regex是正则表达式的简写,后面再加一个r,然后.com。这是一个正则表达式的速查速记、速写网站。它有非常全面的功能,可以说是学习正则表达式的瑞士军刀。
我们可以看到,它是一个Github上面的开源项目。我们可以点击它的Github地址,这个项目有将近1万的star,可以说非常受到欢迎。我们在regexr后面再加上一个cn,就会进入到这个网站的中文版。
这里可以直接填入一个表达式,对下面的测试文字进行匹配。比如我填写Reg,这里就匹配出了文字。这里前后两个灰色的斜线代表中间这一块是正则表达式,
后面这个小写的g是正则表达式的标识符。这个小写的g代表global,也就是匹配所有符合要求的字符串。如果我们去掉这个小写的g,那它只匹配一次。
我们可以在这里的标识把小写的g去掉,这样他就只匹配到了第一次。
下面还有忽略大小写,还有匹配多行等等。我们可以在左侧找到这里的备忘单,就可以速查正则表达式的语法。
大部分正则表达式的语法都很直白,没有必要死记硬背,这里查上就可以直接使用。
这里唯一一个需要理解的就是这个捕获分组,我来重点讲一下。
捕获分组的意思就是这一对小括号,它的意思是把小括号里面的内容作为一个小单元进行处理。
比如这个小单元里面我填上er,这里的意思是把er这两个字母作为一个小单元。比如,我们可以约定这个小单元出现的频率。我们从左侧的速查表这里找到,这里用花括号包裹起来的是量词,表示刚好出现几个。比如我要求这个小单元刚好出现两次,这里就匹配到了这个部分,表示er这个小单元刚好出现了两次。
分组还有一个重要用法,就是用来快速提取数据。比如这里我有一个年份,我要提取里面的年月日。我们先用正则表达式把它的全文匹配一下。我们通过这个速查表往上找,表示0-9中任意一个数字的是这个\d,然后后面我加上它的量词四个横线,然后再反斜线d,量词这就两个,然后再横杠,再反斜线d,量词两个。这样我们就匹配上了整段。
然后我们需要把年月日都提取出来,这里就使用小括号进行划分小单元。这里我们先把年份划分成一个单元,月份划分成一个单元,最后是日期划分成一个单元。我们再把鼠标指上去,这里显示正则表达是匹配到了整个日期,一分组是年份,二分组是月份,三分组是日期。
好,我从js代码里面演示一下。这里我点击键盘上的F12,找到这里的控制台。我敲上这段代码,这是待匹配的文本,然后我的正则表达式。
接下来我们进行匹配,匹配出来的第零个就是完整字符串,1是第一个小分组,也就是年份,2是月份,3是日期。我们回车,可以看到这里程序的输出。
这个正则表达式真的很难一眼看懂他到底要表达什么,需要匹配什么。这里我要介绍第二款工具 https://regex-vis.com/ 。这里的VIS指的是visual,就是可视化。这是一个正则表达式可视化的工具。我们可以看到,它也是一个Github上面的开源软件。
好,我把刚才那个表达式粘过来,这里立即生成了一个正则表达式可视化的一个图表。
我们可以点击每一个模块,右侧这里表达式高亮出来的内容代表每块对应的表达式。
首先这个上箭头代表这一行的开始,后面是http。接下来这个s出现0次或者一次,代表可以有这个s,也可以没有。后面是冒号双斜线。
我们可以看到这里,一个点然后后面英文字母出现2-6次,这代表一个顶级域名。比如.top、.cn、.com,这就是顶级域名。左半部分这里就是主域名,然后在左边可以出现0次到1次的这一块,这里就是子域名。
顶级域名的右边可能会出现一个斜线,斜线后面的这一部分就是URL的路径(path)。
所以这整个正则表达式要匹配的就是一个http(s)的URL链接。我们读懂以后,把这个表达式还是复制到刚才的这个regexr这个网站下面,就可以输入文本进行测试。比如这里测一下我的域名,这里就匹配上了我的网址。我们可以看到第一分组是我的主域名,第二分组是后面的这个path。
说到写正则表达式,那我们就可以借助AI了。这里我用ChatGPT演示一下。爬爬虾之前往期视频有介绍过如何在国内免费使用ChatGPT,
还有Claude的这两个顶级AI大模型。
www.baidu.com
google.com
news.com
map.baidu.com
tech-shrimp.net
baid.net
shrimp.tech
使用正则匹配所有的非baidu.com的域名
我们先看第一个例子:使用正则表达式匹配所有非baidu.com的域名,然后上面给了一组测试数据。我们使用AI写正则表达式有一个技巧,就是把你的测试数据直接作为prompt写到这个输入框里面,有助于他生成更精准的正则表达式。
173.39.32.33 -- [29/0ct/2018:08:48:53 +0800] "GET /static/assets/vottaweb-elements/index.is HTTP.1" 200 173837 "https:/kj.u.rizhiyi.com/"Mozilla/5.0 (Windows NT 6.2: WOW64) AppleWebkit/537.36 (KHTML, like Gecko)Chrome/63.0.3239.132 Safari/537.36" "_" 0.150 0.01
用正则匹配上面日志里面的 GET作为method, 200作为 http code 173837作为bytes
我们来看第二个例子。在这个例子中,我需要用正则表达式匹配出这里的GET作为http的method,然后这里的200作为HTTP code,这个137837作为请求的字节数。所以我需要三个分组。我们来看一下。
好,我们把这个正则复制下来,过来测一下。我们把鼠标移上去,
看到第一分组是GET,第二分组200,第三分组137837。还是难不倒他,完全没有问题。
我们看下一个例子:使用正则表达式匹配两个$符之间的所有数据。如果这种前面是一个$符或者3个$符的,都不能进行匹配。我们还是使用那个技巧,尽可能多的给chatGPT测试数据,这样它会生成的结果更准确。
请使用正则表达式匹配所有两个$
符号中的数据。
需要匹配的
$$ a = a^2 $$
$$123$$
$$ A $$
$$ a = a^2 $$
$$123$$
$$ A = a/$$
$$ a^{2}+ 3\$$
$$ 9999 $$
$$ 0987 $$
$$3\frac{2}$$
不能匹配的
abc$asddadd$$
$$$ a=b^2 $$
abc$asddadd$$
$asddadd$
$ b = a ^ 2$
abc$ a=b^2 $$abc
abc$$$ a = a**2 $$
$$$$ a=b^2 $$
abc$asddadd$$¥
$$$a=b^2 $$$$
这是ChatGPT生成的正则,我们来测一下。我们先测一下这些可以匹配到的,可以看到都匹配到了。
我们再测一下这些不能匹配到的,这里就没有匹配到。
我们再去可视化网站看一下。这里使用了负向后行断言还有负向先行断言,
保证了开头结尾只有两个$而不是3个。然后中间使用group把中间的内容匹配出来了。