theme: channing-cyan
highlight: a11y-dark
本文正在参加「金石计划 . 瓜分6万现金大奖」
正则表达式 进阶🛫
前言
推荐先阅读
再阅读本文。
本文主要讲解是关于 正则表达式 中,分组 和 区间
1.分组
顾名思义就是将我们写的 正则字符或者数字 通过 ()
进行包裹,合并组合在一起,然后进行 分组管理。
那么每个 括号,代表一组。当然也称 捕获组。
这就引出下面的两个概念 分组引用 和 回溯引用
1.1 分组引用 $
既然我们通过 ()
分组了,那么我们要做的肯定就是获取里面的值。
- 获取值的方式为:
RegExp.$number
可能上面讲的比较抽象,这里用大白话,理解一下
-
从第一个括号出现,我们获取里面的值,就通过
RegExp.$1
-
第二个括号,就是
RegExp.$2
-
… 以此类推
那你可能会有疑问?为什么不从下标 0 开始?有没有 RegExp.$0
这个东西?
-
首先
RegExp.$0
这个是不存在的 -
如果我们打印,得到的也只是
undefined
案例1
这里举个例子,我们来好好理解一下这个 分组引用:
const string = '2022-11-05'
const string2 = '2022-11-06'
const reg = /(\d{4})-(\d{2})-(\d{2})/
reg.test(string) // true
reg.test(string2) // true
console.log(RegExp.$0)
console.log(RegExp.$1)
console.log(RegExp.$2)
console.log(RegExp.$3)
可以看到,我们分了 3 组,得到的结果值如下
看的这个结果,此时你可能会疑问,为什么它拿的最后一个,而不是第一个,这就有意思了!
-
那我们将
string
和string2
反过来换个顺序再看一下const string = '2022-11-05' const string2 = '2022-11-06' const reg = /(\d{4})-(\d{2})-(\d{2})/ reg.test(string2) reg.test(string) console.log(RegExp.$0) console.log(RegExp.$1) console.log(RegExp.$2) console.log(RegExp.$3)
可以看到确实拿的是最后一个
说明
RegExp.$number
匹配到的是最新的值 -
这里可以 再多做一个操作,来验证一下
const string = '2022-11-05' const string2 = '2022-11-06' const reg = /(\d{4})-(\d{2})-(\d{2})/ reg.test(string) console.log(RegExp.$0) console.log(RegExp.$1) console.log(RegExp.$2) console.log(RegExp.$3) reg.test(string2) console.log(RegExp.$0) console.log(RegExp.$1) console.log(RegExp.$2) console.log(RegExp.$3)
通过这个结果,我们可以更加确定,我们的结论
RegExp.$number
的值 是 匹配到的是最新的值 -
漏洞
其实这个结论,目前看来并不是完全对,
因为可以看到,上面都是匹配成功的,也就是说上面的例子
reg.test()
的值都是true
但是如果这个值为
false
结果又是什么?这里把
string2
的值进行修改const string = '2022-11-05' const string2 = '2022/11/06' const reg = /(\d{4})-(\d{2})-(\d{2})/ reg.test(string) reg.test(string2) console.log(RegExp.$0) console.log(RegExp.$1) console.log(RegExp.$2) console.log(RegExp.$3)
可以看到结果是
string
的,所以我们的结论应该是RegExp.$number
的值 是 最近匹配成功 的值
但是,也因此暴露出来一个问题,就是通过
RegExp.$number
这个方式来获取,是很不稳定。 -
推荐
最后,这里推荐各位小伙伴,确认了,只有匹配成功了
我们才去获取括号里面的值,去做相关的处理
const string = '2022-11-05' const reg = /(\d{4})-(\d{2})-(\d{2})/ if (reg.test(string)) { console.log(RegExp.$0) console.log(RegExp.$1) console.log(RegExp.$2) console.log(RegExp.$3) }
总结1
-
通过
RegExp.$number
的方式来获取分组的值 -
它匹配的是最近成功的结果值,然后存放起来。
-
由于直接使用
RegExp.$number
来获取值,有点不稳定所以我们需要
reg.test()
判断成功后,再去执行某些操作
1.2 回溯引用 \
上面讲了 分组引用 $ 的使用
我们知道了,可以在 匹配成功后,通过 RegExp.$number
的方式,来获取到值。
那接下来,我们理解一下 回溯引用 \
疑问1
先抛出问题
-
什么是 回溯引用 \ ?
-
它与 分组引用 $ 有什么区别呢?
-
再或者说什么场景下,我会用到 回溯引用 \ 呢?
举个🌰
现在,有这么这么一个需求,小伙伴们先看下:
-
例如,我想要将 连着重复的数字 找出来
const str = 'wzms123,wzms11,wzms222,wzms3333,wwzzmmmssss'
该怎么找?该怎么处理?
难道用
for
循环,一个一个来?哇哦 😲我直接一个 达咩🙅🙅♂️
好了,下面我会通过这个需求,来慢慢讲解下 回溯引用 \
解答1
既然要找重复数字的,那么我们看图,直接分析这个字符串中,有哪些重复的!
可以看到有三处
那我们通过之前的知识,能够知道 元字符\d
是匹配数字的,那我们先试一下。
const str = 'wzms123,wzms11,wzms222,wzms3333,wwzzmmmssss'
const reg = /(\d)/g
const result = str.match(reg)
这里将所有的数字都匹配出来了。但我们想要重复!
此时观察下,我将 (\d)
通过 括号 包括起来了,说明 (\d)
是一个组,我们匹配到的值,将会放到这个组里面。
逻辑如下:
-
遇到数字
(\d)
会进行匹配,然后把这个 数字值 放到组中 -
那我们就只需要重复使用 这个组 中的值,就可以了
思路没问题,那用什么表示这个重复的值呢?
-
那就用到我们的 回溯引用 \
-
当然 回溯引用 \ 也有人喜欢叫 反向引用 \,看个人想叫什么都行。
来,那就针对上述问题,先写下代码,再解释
const reg = /(\d)\1/g
-
对于出现的第一个括号
(\d)
,代表 第一组 -
用
\1
代表 第一组 所匹配到的值。 -
一定要注意 回溯引用 \,它是用在 正则表达式 中的
那我们这里先简单总结下 回溯引用 \:
写法:
-
从第一个括号
()
出现,这个括号里面的值,通过\1
来表示 -
第二个括号
()
出现,则这个括号里面的值,通过\2
来表示 -
依次类推…
使用位置: 是用在 正则表达式 当中
处理这个问题
可以看到这个问题,其实并没有结束
我们这个结果并不符合我们的预想,我们想 333
这个值,是连续的,而不是断开的 33
、33
这就用到我们的 重复 +
const reg = /(\d)\1+/g
可以看到结果就是我们最开始的预期了,是不是很好用😄
案例2
对于上面的案例,只出现了一个 分组,这里再举个例子,来讲解多个 分组下,回溯引用 \ 的使用
针对下面字符串,找到
const str = 'wzms1212334545,wwzzmmmssss'
const reg = /(\d)\1/
2.区间 []
首先说一下 区间 在 正则表达式中 的写法为 []
其次,区间 分为 几个 部分,包括 集合 、范围、取反
区间 是较为复杂点点,因为里面的情况很多
-
可以说 区间 里面的语法,相当于里面是一个全新的 正则表达式语法
内心:😅😅😅
-
不过深入理解后,其实还好!
不多说,一起来攻破它!
2.1 集合
这里通过🌰来讲解:
案例1
这里有四个字符串,判断 w
字符 或者 z
的字符,是否在这个字符串内
const str1 = 'abc123' // false
const str2 = 'abcwe123' // true
const str3 = 'abcmn123' // false
const str4 = 'abc123zf' // true
如果不用正则表达式,则我们可能需要 String
类型的 includes
或者 indexOf
方法来判断,而且还得写两遍
而用 正则表达式,则只需一遍即可
const reg = /[wz]/g
reg.test(str)
可以看到是成功匹配的,那这个原理是什么呢?来详细分析下这个正则表达式
-
可以看到
[]
包裹着w
字符 和z
字符- 其实代表的意思就是 这两个字符中的任意一个
w
、z
,存在即可
- 其实代表的意思就是 这两个字符中的任意一个
案例2
通过面的案例可能不是很全,这里再来一个,可以更深入了解 区间 的 集合
我想得到这样的 字符串: 好x你
。可以是 好爱你
、好想你
、好烦你
,其它的一律不可以。
const str1 = '好想你' // true
const str2 = '好像你' // false
const str3 = '好想爱你' // false
const str4 = '好爱你' // true
先分析下
-
首先看到 第一个 和 最后一个 字符是固定的
- 则需要
^
和$
这两个元字符
- 则需要
-
其次中间的值,可以为
爱
、想
、烦
通过上面的栗子,其实可以很快写出正则
const reg = /^好[爱想烦]你$/g
注意 第三个 好想爱你
,它的结果是 null
,这说明了什么。
- 说明确实只会匹配 区间 内的字符一次,不会匹配多次的。
提高
好,我们这里成功完成,然后你正准备,拍桌子,下班,开溜🏃!
产品过来说,稍等一下,现在紧急又需要你支持第三个 好想爱你
这种,以及它们之间 两两结合
此时你的选择是:
- 摔桌子走人,谁爱干谁干
- 留下改代码
那当然是 打工人,打工魂😭😭
那我们快速处理下:
虽然看起来 两两组合,会比较烧脑,但是对于 正则 来说,很简单
const reg = /^好[爱想烦][爱想烦]?你$/g
可以看到非常成功就实现了,但是却不是很优雅
更优雅的为
const reg = /^好[爱想烦]{1,2}你$/g
2.2 范围
从上面知道了 集合 是什么之后,那么这个 范围 就很好理解了
就是 在某个 范围 里面,任意一个,存在即可
范围 是通过 -
字符来连接,当然这个也是在某些特殊情况下能代表 范围,常见的有下面几个
[a-z] // 代表的是小写字母a 到 小写字母 z
[A-Z] // 代表的是大写字母A 到 大写字母 Z
[0-9] // 代表的是数字 0 到 9
也可以进行组合
[a-f0-4] // 代表字符 abcdef01234
[a-zA-Z0-9] // 代表所有的字母和数字
这里还是通过例子来讲解
案例1
在一些网站中,需要我们在注册时,提供手机号,并且一般都会对我们的手机号做检验
-
长度为
11
位 的 纯数字 -
并且数字1作为开头
-
第二位则是
3456789
中的任意一个
const str = '13839812345'
const reg = /^1[3-9][0-9]{9}/
reg.test(str)
可以看到用 正则表达式 可以很快处理我们的这些问题
正好,这里也整个花里胡哨的 \d{8}
const str = '13839812345'
const reg = /^1[3-9]\d{9}/
reg.test(str)
通过这个例子,我们可以看到 区间 中 范围 的使用
2.3 取反
如果看过 手摸手快速入门 正则表达式 (基础)🛫 这篇文章,则知道什么是 取反 操作
当时说,会对 区间 进行 取反 操作
就是到这里,下面讲解下
-
取反 是字符
^
标识,并且最主要的是,只有它在 区间 的 开头 才能表示 取反 操作 -
例如
/[^abc123]/
- 上面这个表达式的意思,就是 匹配除了
a、b、c、1、2、3
之外的任意字符
那你猜猜,能不能匹配到
^
字符呢?- 结果是能匹配到的
- 上面这个表达式的意思,就是 匹配除了
-
例如
/[^0-9]/
和/[^\d]/
- 表示 能够匹配数字以外任意字符,与
\D
的作用一样。
- 表示 能够匹配数字以外任意字符,与
-
而
/[abc^123]/
则不会代表 取反 的意思const reg = /[abc^123]/ const str = '1' const str = '^' reg.test(str) // true reg.test(str2) // true
2.4 转义
我们知道 转义 字符是通过 \
来表示
而对于 区间 里面出现的字符,绝大多数都只是普通形式
-
例如
/[.+?()]/
代表的仅仅只是字符
.、+、?、(、)
这个字符本身 -
我发现的 特殊的需要 转义 的字符有 2 个,
]、\
,而且这两个还有不同,我们看下-
在对
]
进行匹配时const reg = /[123\]]/ const str = ']' reg.test(str) // true
-
在对
\
进行匹配时,则需要两个\\
const reg = /[123\\]/ const str = '\\' reg.test(str) // true
-
3. () [] {} 区别
由于 () [] {} 这三个符号,很容易混淆,所以这里,再对这三个符号,做一次汇总,就能够完全了解了。
()
()
代表分组,每一个组,里面都是一个小的 正则表达式
它有两个大块,分组引用 和 回溯引用
-
通过
RegExp.$number
来获取值 -
通过在 正则表达式 中使用
\number
来获取每个 分组 里面,所匹配到的值
[]
[]
代表 区间,匹配某个字符,是否在这个 中括号区间 里,只要存在即可匹配成功
它拥有 集合、范围、取反、转义 几大部分
{}
{}
代表 重复,代表重复几次
可以是单个数字 {5}
代表重复5次
也可以是范围 {5,10}
代表可以重复 5 到 10 次
暂无评论内容