一文破解正则密码

发表于 2年以前  | 总阅读数:375 次

前言

正则,熟悉的陌生人,我们在表单校验中见到它,也在框架源码 html 转 ast 树的 parser 原理中见到它;常常见到,需要时百度一搜,确实能用,却又一碰到就发憷,原因很简单,这火星文,谁看得懂呀!

本文目标,带你走进正则世界,作为一篇认真负责的科普文,一定要做到让你们一遍学懂却不会,于是反复来查看。

正则历史

正则其实就是规则的设定,用于验证或者获取信息。

真正起源于神经网络

20 世纪 40 年代,两位神经生理学家研究出了一种用数学方式描述神经网络的方法,并以此在 1956 年发表了一篇论文《正则表达式搜索算法》,主要描述了一种叫做正则集合(Regular Sets)的符合。

在计算机世界大放异彩

UNIX 之父在十年后的 1968 年,发表文章《正则表达式搜索算法》,并将正则移植到了大名鼎鼎的文本搜索工具grep中。

正则为什么存在

理解一个东西,不要一上来就背应用层的 API,要去理解,人的大脑本来就是被设计成对理解的东西很容易记忆,不要浪费自己的天赋。

我们说过,正则其实就是规则的设定,用于验证或者获取信息。匹配动作最粗暴的无疑是一一对应,a 对 a,b 对 b,这个规则就是完全一样才匹配,但这无疑太低效;一个事物很容易有共性,共性构成集合,比如手机号 13 位,邮箱带@等等,正则就是让我们更高效的匹配或获取这些特定规则集合的存在。

正则如何做到

正则中的处理方式就是设定子规则,让某些符号不再代表本身,而是代表一些子规则,就像搭建大楼,我们希望找到自己想要的规则,就得用合适的最小砖块,再设定使用量,就搭建完成了。

这个子规则,就是元字符,如我们常见的\d,代表单个 0-1 数字,\s就是换行指标等空白字符;需要注意的是,我们刚刚一直在强调单个,这其实也很好理解,对于文本而言,最小单元自然是单个字符,有了最小单元,我们再加上重复规模,就可以搭建我们自己的大楼了。

至此,我们对正则世界基本的了解算是到位了,开始更接地气的分享叭!

砖块:元字符

那我们先来了解元字符,有四个维度,分别是【字符组】、【取反字符组】、【常用字符组】、【空白字符】,可以记忆为 【3 + 1】,依次理解

字符组

基础使用

对于单字符选择而言,在正则中的术语被称为字符组,接下来我们都会用这个术语,但不要被迷惑,它并不是匹配一组数据,而只是匹配一组数据中的一个字符,这点很关键。

语法:[xxx]

匹配规则: 目标文本需包含【任意一个包含在括号中的元素】

获取信息规则:将获取第一个【任意一个包含在括号中的元素】

举例:/[abc]/这个正则将匹配 a、b、c 中的任何一位且只有一位,默认匹配第一位,使用测试平台会得到如下结果

取反字符组

取反逻辑

正常使用是范围内选取,不过也会出现【除了这些之外】的范围选取,这时就需要用到取反了

语法:[^xxx]

匹配规则: 目标文本需包含【任意一个不包含在括号中的元素】

获取信息规则:将获取第一个【任意一个不包含在括号中的元素】

举例:/[^abc]/这个正则将匹配非 a、b、c 中的任何一位且只有一位,默认匹配第一位,使用测试平台会得到如下结果

常用字符组

八二原则同样适用在字符组中,有很多常见的匹配规则,没必要重复写,于是正则就把这些特殊字符组分别取了个别名

主要分为如下【3+1】概念,三对+一个

使用符号 规则 对应字符组
\d 单个数字 [0-9] (digit 数字)
\D 单个任意非数字 [^0-9]
\w 单个任意数字字母下划线 [0-9a-zA-Z_] 数字字符下划线
\W 单个任意非数字字母下划线 [^0-9a-zA-Z_] 非单词字符
\s 单个任意空白符 [ \t\v\n\r\f] 表示空白符 (空格、水平制表符、垂直制表符、换行符、回车符、换页符)
\S 单个任意非空白符 [^ \t\v\n\r\f]
. 单个除换行符外任意字符 [^\n\r\u2020\u2029] 通配符 除换行符、回车符、行分隔符、段分隔符外任意字符

其他常用字符组

对应字符组 对应字符组
[\d\D] [\s\S] [\w\W] [^] 任意字符

空白字符

这类字符比较特殊,单独拎出来,方便后期直接使用

到此,我们也就知道了如何去匹配单个字符,这就是我们的“最小规模”,但一个个匹配肯定是不行,那正则将冗长到难以忍受,所以我们还需要重复,这就是量词的作用。

要多少块砖:量词

理解了字符组,我们就要了解规模了,这在正则中有个术语 --- 量词,还是【3+1】,依次理解

这个没有很复杂的东西,唯一要注意的是,正则默认是只匹配一次的,即一次匹配完后就算后文还有符合的内容也不再获取,这涉及到修饰符g,后面再补充;

看案例就行,我们还是以[abc]作为字符组最小单元来演示。

*号:0-n 次

正则:/[abc]*/

匹配规则: 目标文本无需包含【任意一个包含在括号中的元素】,此匹配规则一定成立

获取信息规则:将获取第一段【包含在括号中且连续的元素组】

+号:1+n 次

正则:/[abc]+/

获取信息规则:将获取第一段【包含在括号中且连续的元素组】

匹配规则: 目标文本需包含【至少一个包含在括号中的元素】

?号:0 次或 1 次

正则:/[abc]?/

匹配规则:此匹配规则一定成立

获取信息规则:将获取第一个【任意一个包含在括号中的元素】

{}符号:精确控制次数

上面其实都属于特殊案例,我们可以通过{}精确控制匹配次数,主要有三个用法

  • {m}:必须出现 m 次
  • {m, n}:可以出现 m-n 次
  • {m,}:至少出现 m 次

我们对这三种情况进行演示,动图如下

量词模式

量词还涉及到模式问题,因为量词有范围,这就意味着可取多可取少,但计算机是不允许有歧义的,所以量词存在三种模式

  • 贪婪模式:默认,会尽可能匹配多的内容
  • 懒惰模式:量词后面加个?,会尽可能少匹配内容
  • 独占模式:量词后面加个+,不触发回溯动作

举例见模式区别

测试用例:aaabb

测试正则:

  • 贪婪模式:/a*/
  • 懒惰模式:/a*?/
贪婪模式:/a*/

匹配过程:

匹配结果:

对应输出结果:['aaa','','','']

懒惰模式:/a*?/

匹配过程:

匹配结果:

对应输出结果:['','a','','a','','a','','','']

补充案例

至此,我们就完成了对量词规则的学习

正则模式

既然量词有模式,正则本身自然也有模式,针对【大小写、多行、点通配、备注】情况,存在【3+1】种模式

  • 不区分大小写模式
  • 点通配模式
  • 多行匹配模式
  • 注释模式

我们来逐一了解

不区分大小写模式(Case-Insensitive)

语法:/(?i)reg/ 对应 js 为 /reg/i

注意点:

  1. 不区分大小写模式的指定方式,使用模式修饰符 (?i);
  2. 修饰符如果在括号内,作用范围是这个括号内的正则,而不是整个正则;

作用: 忽略大小写进行匹配

正则:/(?i)(cat) \1/ 对应 js 为 /(cat) \1/i

如果这时候我们希望重复单词间保持大小写完全一致,可以使用如下正则

正则:/((?i)cat) \1/ 对应 js 为 暂无

点通配模式(单行匹配模式 -- Single Line)

语法:/(?s)reg/ 对应 js 为暂无

注意点:

作用: 使得.元字符可以匹配包括换行在内的所有字符

多行匹配模式

语法:/(?m)reg/ 对应 js 为/reg/m

注意点:

作用: 使得^$可以匹配上每行的开头或结尾

使用前正则:/^the|cat$/

使用后正则:/(?m)^the|cat$/ 对应 js 为/^the|cat$/m

注释模式

语法:/(?#)reg/ 对应 js 为 暂无

注意点:

作用: 使得正则支持添加备注信息

使用正则案例:/(\w+)(?#word) \1(?#word repeat again)/

正则位置信息

对于匹配而言,就像我们看一个人是不是自己要找的人,不只有对着画像、照片一直看这一个方法,也可以描述 TA 在什么东西的旁边、TA 面前是什么、背后是什么等等,这些位置信息在正则中同样有需求,并且有个专门的术语 -- 断言

断言,即断定匹配文本的位置关系;前后的内容是什么、中止的位置在哪之类,落实下来分为三类:单词边界行的开始/结束环视

行的开始/结束

这个我们或多或少都接触过,如果我们要求匹配的内容出现在一行文本的开头或结尾,就可以使用^$进行位置界定。

结合之前说的【模式】中多行模式的概念,默认处理文本会被正则当成一行进行处理,无论其是否换行,这是的开始结束就等同于文首和文末;而如果想处理多行情况,只需要改变模式为多行匹配即可,js 中语法为/reg/m

单词边界(Word Boundary)

多行模式+^$可以在行的维度处理边界问题,但如果是单词,就无能为力了,如我们希望在下面文本中替换tom这个人名为jerry

tom asked me if I would go fishing with him tomorrow.

这时如果替换的正则是/tom/ ,就会出现这种错误的替换现象

很明显,我们要的就是tom,而并不是只要包含 tom 就可以的部分,这时我们就可以使用到单词边界的概念,设定开始截止,避免出现匹配歧义。

基础概念

语法:\b

作用: 匹配到\w即【[A-Za-z0-9_]】表示范围之外的字符就中止匹配,可以理解为边界(Boundary)

实例

环视

我们刚刚说了边界,包括单词和行的边界,其实边界也就是要求匹配文本的前后一定是特定的内容,只是这个特定内容对行来说是^$,对单词边界来说是$

那我们把这个特定范围再灵活点,对于一段内容而言,有前后两个方向、满足或者不满足两个情况,意味着有四种情况,如下表。

总结下来其实就是:有尖括号则为左,等号肯定感叹否

正则逻辑信息

根据前文,我们已经学习了【字符组】和【量词】的概念,就像一门编程语言,有组成物料还不够,自然还需要一些逻辑判断,在正则中也存在【逻辑元字符】这一概念。

逻辑元字符

|号:或逻辑

某个资源可能以 http:// 开头,或者 https:// 开头,也可能以 ftp:// 开头,那么资源的 协议部分,我们可以使用 (https?|ftp):// 来表示。

正则优先级提升之分组

在正则中存在分组的概念,主要有两点作用:整体和复用。

整体

代表避免语义分析有歧义,如【匹配 15 位数字或 18 位数字】,这时如果写出这样的正则/\d{15}\d{3}?/;后面的\d{3}?将代表懒惰模式匹配,这个正则会只匹配 18 位数字而非 15 位

测试正则:/\d{15}\d{3}?/

这里就存在确定\d{3}是一个整体的需求,这可以使用分组实现

测试正则:/\d{15}(\d{3})?/

复用

有些时候,我们也会需要用到之前匹配到的结果,如【查看文本中的连续重复单词】,解决思路就变成了

  1. 写出匹配单个单词的正则
  2. 使用之前的结果进行再次匹配

第二点,就是通过分组实现的;先了解下基础概念

基础概念

语法: 定义使用() ,正则中访问使用\编号,方法中访问使用$编号

作用: 用于分组,被括号括起来的部分默认将被保存为子组,正则中可以通过子组编号访问,子组编号从一递增,也可以用语法(?:)从而不保存子组,避免占用编号。

分组引用语法详解

分组引用

假定分组编号为number,则可以使用\number进行引用

多编号情况

左括号是第几个,那就是第几个分组

不保存子组

使用此语法后不会为这个子组分配编号

替换功能

命名分组

V8 目前已经完全实现了命名捕获分组的提案 https://tc39.github.io/proposal-regexp-named-groups/,一起来了解下吧!

基础概念

语法: 定义使用(?<name>) ,正则中访问使用\k<name>,方法中访问使用$<name>

作用: 用于命名分组,不再使用编号访问而是直接通过分组变量名访问,更加准确

API 结合解构赋值

在 js 关于正则的方法中,如果存在命名分组,会存在groups属性,里面存放着每个命名分组的名称以及它们匹配到的值;结合解构赋值,会有很神奇的功效;

在 exec() 和 match() 中的使用:

exec() 和 match() 方法返回的匹配结果数组上多了一个 groups 属性,里面存放着每个命名分组的名称以及它们匹配到的值

const {day, month, year} = "04-25-2017".match(/(?<month>\d{2})-(?<day>\d{2})-(?<year>\d{4})/).groups 

在 replace(/.../, replacement) 中的使用:

replacement为函数时,在实参列表的最末尾,多传了一个 groups 对象

"04-25-2017".replace(/(?<month>\d{2})-(?<day>\d{2})-(?<year>\d{4})/, (...args) => {
  const groups = args.slice(-1)[0]
  const {day, month, year} = groups
  return `${day}-${month}-${year}`
}) 

正则编程

这是最最关键的部分,学来就得用上呀,我们来分享在正则在前端编程中的应用。

正则最终还是要落实到编程语言中来,让我们来看下正则编程吧!

正则的处理可以区分为如下四类:

  • 校验文本内容
  • 提取文本内容
  • 替换文本内容
  • 切割文本内容

让我们逐一了解

校验文本内容

需注意:关于 lastIndex,即正则会将下一次匹配开始的位置 ;字符串的四个方法,每次匹配都是从 0 开始的,即 lastIndex 不变;而正则的两个方法 exec 和 test ,如果是全局匹配,则每次匹配完都会改变 lastIndex 的值,这就会导致可能出现【处理两次,第一次成功,第二次失败】的情况。

var regex = new RegExp(/^\d{4}-\d{2}-\d{2}/, 'g')
regex.test('2021-12-21') // true
console.log(regex.lastIndex ) // 10
regex.test('2021-12-21') // false
console.log(regex.lastIndex ) // 0

由于我们这里是文本校验,并不需要找出所有的。所以建议 JavaScript 中文本校验在使用 RegExp 时不要设置 g 模式。

字符串方法:search

search 会将字符串转为正则

正则方法:test

提取文本内容

字符串方法:match

match 会将字符串转为正则

注意:match 方法的返回值与修饰符 g 有关(没有匹配上时返回 null)

  • 没有 g :返回标准匹配格式,即:数组的第一个元素是整体匹配的内容,接下来是分组捕获的内容,然后是整体匹配的第一个下标,最后是目标字符串
  • 有 g :返回的是一个包含所有匹配内容的数组

正则方法:exec

exec 比 match 更强大,可以解决 有修饰符 g 时 match 没有索引信息的问题,在使用 exec 时,正则会将下一次匹配开始的位置存放在正则的属性 lastIndex 上

替换文本内容

字符串方法:replace

切割文本内容

字符串方法:split
  • 可以有第二个参数,表示结果数组的最大长度
  • 如果正则使用分组时,结果数组中是包含分隔符的

前端相关 API 总结

  • string

  • match

  • split

  • search

  • replace

  • RegExp

  • test

  • exec

总结

做下总结吧,绘制知识图谱,方便自己记忆,也方便和人分享

3 + 1 元字符;3 + 1 常用元字符;3 + 1 正则量词;3 量词匹配模式;3 + 1 正则匹配模式;3 + 1 正则逻辑

首先物料元字符,有四个维度,分别是【字符组】、【取反字符组】、【常用字符组】、【空白字符】,可以记忆为 【3 + 1】;

理解了字符组,我们就要了解规模了,这在正则中有个术语 --- 量词还是【3+1】;

量词还涉及到模式问题,因为量词有范围,这就意味着可取多可取少,但计算机是不允许有歧义的,所以量词存在三种模式;

既然量词有模式,正则本身自然也有模式,针对【大小写、多行、点通配、备注】情况,存在【3+1】种模式;

就像定位,不止需要本身的绝对信息,还需要看他的相对位置信息,这个信息在正则中叫断言,存在三种情况,【行首尾、单词边界和环视】,其中环视又存在前后是不是四种情况

就像编程语言,我们有了零碎的物料是不够的,还需要逻辑,在正则中存在分支语句|和优先级分组,分组又有三类,默认分组、非捕获分组和命名分组

至此,我们也就用非常精炼的总结性语句概括了正则的整体脉络啦!

尾声

少年们,心法已定,拿走不谢,希望我能做到让你们一遍看懂而记不住,要首尾呼应,尝试动手自己实现下吧,有些需求会发现如果用正则的角度,会有很多很神奇的实现方式呀,而且如果能帮助到别人,也超有成就感的。

本文由哈喽比特于2年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/T0JFH618B_BVTzTr8m31bw

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237270次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8108次阅读
 目录