本文正在参加「金石计划 . 瓜分6万现金大奖」
王志远,微医前端技术部
前言
根据前文,我们已经学习了【字符组】和【量词】的概念,就像一门编程语言,有组成物料还不够,自然还需要一些逻辑判断,在正则中也存在【逻辑元字符】这一概念。
此外,我们知道编程里都有运算符权重的问题,比如先乘除后加减,在正则中如何提升多个元字符的优先级使之成为一个整体呢?同样是括号,只不过在正则中它被称为分组。
逻辑元字符
|号:或逻辑
某个资源可能以 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})?/
复用
有些时候,我们也会需要用到之前匹配到的结果,如【查看文本中的连续重复单词】,解决思路就变成了
-
写出匹配单个单词的正则
-
使用之前的结果进行再次匹配
第二点,就是通过分组实现的;先了解下基础概念
语法: 定义使用() ,正则中访问使用\编号,方法中访问使用$编号
作用: 用于分组,被括号括起来的部分默认将被保存为子组,正则中可以通过子组编号访问,子组编号从一递增,也可以用语法(?:)从而不保存子组,避免占用编号。
分组引用
在一次成功的匹配中,每一个括号包裹的结构都是一个分组,将会存储在一个空间内容,由 RegExp 的静态属性2...访问
分组引用
假定分组编号为number,则可以使用\number进行引用
多编号情况
左括号是第几个,那就是第几个分组
不保存子组
使用此语法后不会为这个子组分配编号
替换功能
命名分组
V8 目前已经完全实现了命名捕获分组的提案 tc39.github.io/proposal-re…
基础概念
语法: 定义使用(?<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}`
})
模式
在正则中,存在模式的概念,主要是改变元字符的匹配行为,提供对一些特殊情况的处理,目前有四种:
- 不区分大小写模式
- 点通配模式
- 多行匹配模式
- 注释模式

我们来逐一了解
不区分大小写模式(Case-Insensitive)
语法: /(?i)reg/ 对应 js 为 /reg/i
注意点:
- 不区分大小写模式的指定方式,使用模式修饰符 (?i);
- 修饰符如果在括号内,作用范围是这个括号内的正则,而不是整个正则;
作用: 忽略大小写进行匹配
正则: /(?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)/