场景
有时我们需要匹配一些字符,但要求前后必须是特定内容,但又不想把这些特定内容匹配到最终结果中,这时,使用正则的零宽断言能实现我们想要的效果
概念:什么是零宽断言?
- 零宽:意如其名,是一种零宽度的匹配,即它匹配到的内容不会保存到匹配结果中去,
- 断言: 做出的假设,在正则中可以理解为是正则表达式的一种条件判断(当这个条件满足时才正则才能匹配成功),后面我会用例子去验证这个说法
分类
- 按编写位置分:
- 先行断言(写在结果的后面):如果条件成立则匹配前面的结果
- 后发断言(使用
<
符号,写在结果的前面):如果条件成立则匹配后面的结果
- 按条件分(零宽断言是否能匹配)
- 正向:匹配(使用
=
) - 负向:不匹配(使用
!
)
- 正向:匹配(使用
根据位置和条件组合出以下零宽断言格式
- a(?=b) :目的要匹配
a
,但要求a
后面一定要包含字符b
才能匹配(如果a后面有b,则匹配a)- a(?!b) :目的要匹配
a
,但要求a
后面一定不能包含字符b
才能匹配(同上)- (?<=b)a :目的要匹配
a
,但要求a
前面一定要包含字符b
才能匹配(同上)- (?<!b)a :目的要匹配
a
,但要求a
前面一定不能包含字符b
才能匹配(同上)
应用
- 把双花括号中的字符替换成相应数据
const template = `姓名:{{username}},年龄:{{age}}`
const user = {username:'laoxie',age:18}
// 如果[a-z]+前面匹配`{{` 以及后面匹配 `}}`才会去匹配[a-z]+的结果,但`{{` 和 `}}`都不会进入最终匹配结果
const reg = /(?<=\{\{)[a-z]+(?=\}\})/g
const result = template.replace(reg,(key)=>{
return user[key]
})
console.log(result); // => 姓名:{{laoxie}},年龄:{{18}}
- 给金额添加逗号以方便阅读(如:1000000 -> 1,000,000)
const amount = '1000000'
amount.replace(/\B(?=(\d{3})+(?!\d))/g,',') // => 1,000,000
// >说明:`\B` 匹配一个非单词边界(即两个数字之间的位置)
// 如果不用零宽断言,则为以下结果
amount.replace(/\B/g,','); // => 1,0,0,0,0,0,0
// 所以使用断言后表示:如果\B后还有3位数字且3位数字后不能再有数字时,才到\B替换成逗号`,`
所以,合理使用零宽断言,能让我们的正则匹配更加强大,是时候表演真正的技术了
PS:js中的后发断言在ES9中才得以支持,注意浏览器支持情况