看啥推荐读物
专栏名称: 九酒
前端练习生
今天看啥  ›  专栏  ›  九酒

正则匹配之零宽断言

九酒  · 掘金  ·  · 2018-12-02 04:12
阅读 7

正则匹配之零宽断言

当我们需要匹配一些字符,这些字符之前或者之后必须是特定内容的情况时,最明智的一种解决方案应该是零宽断言了。

定义

用于给指定位置添加限定条件(断言),在这个位置之前或者之后满足这个限定条件时,该断言成功。

当断言失败时不会再继续匹配,当断言匹配成功后正则表达式中的其他匹配才会继续。

断言部分也可以是一个正则表达式。

类型

  1. ?= 正向零宽匹配:匹配字符位置后的条件

简单举个例子:

let a = '123ab';
a.match(/\d+(?=ab)/)
//["123", index: 0, input: "123ab", groups: undefined]
复制代码

这个例子是匹配ab字符前面的数字,也就是需要匹配的字符后面需要满足等于ab的条件

  1. ?! 正向零宽不匹配:匹配字符位置后的条件的非

简单举个例子

let a = '132cd';
a.match(/\d+(?!ab)/)
//["132", index: 0, input: "132cd", groups: undefined]
复制代码

这个和上面那个的使用一致,但个人感觉取非不够精确,在正则里取非的范围有点大,所以感觉可能?=更常用一下

举个例子,会出现下面这种情况

let a = '132ab';
a.match(/\d+(?!ab)/)
//["13", index: 0, input: "132ab", groups: undefined]
复制代码
  1. ?<= 负向零宽匹配:匹配字符位置前的条件

简单举个例子

let a = '132ab';
a.match(/(?<=\d)[a-z]+/)
//["ab", index: 3, input: "132ab", groups: undefined]
复制代码

这个例子是为了匹配紧跟数字后面的所有小写英文单词,也就是为了匹配一串小写英文字符串前面必须满足是数字的条件

  1. ?<! 负向零宽不匹配:匹配字符位置前的条件的非

这个与前面的第二种类似,不过是负向的,也就是字符前面应满足断言部分正则表达式,感觉也应该不常用,这里不细写了

组合使用

正向零宽和负向零宽的组合使用,可以简化一些特定的匹配 先举个简单的例子 比如我需要匹配英文字母间的数字

let a = 'qee132ab';
a.match(/(?<=[a-z]+)\d+(?=[a-z]+)/)
//["132", index: 3, input: "qee132ab", groups: undefined]
复制代码

比如我要上面的匹配全局使用

a = 'qee132ab324asd';
a.match(/((?<=[a-z]+)\d+(?=[a-z]+))/g)
//["132", "324"]
复制代码

之前做了一道题,用于匹配字符中变量x的值(比如字符串为‘x=5’,匹配的结果则为5,‘fox=5’,匹配的结果则为null)

这样的匹配使用零宽匹配可以节省很多事

a = 'fox x=5 fox';
a.match(/(?<=\bx=)\d+(?!\d+)/g)
//["5"]
复制代码

总结

零宽断言主要有两个点:

  1. 零宽断言标示后面可以跟一个正则匹配方程式

如上面的例子,(?<=\bx=)零宽标示?<=后面的是一个正则表达式\bx=,当然也可以是其他的任何正则表达式

  1. 零宽匹配完成后匹配的位置仍为当前位置

举个例子

a = '123qwe';
a.match(/(?=\d+)\d+[a-z]+/g)
//["123qwe"]
复制代码

因为零宽匹配后,匹配的位置不变,零宽匹配了第0个位置,第0个位置的后面是数字,所以(?=\d+)匹配成功,值为'',这个时候后面仍需要匹配,因为零宽匹配不移动位置,仍从第0个位置开始,这个时候需要匹配\d+[a-z]+,这个匹配表达式匹配到了123qwe,所以整个表达式匹配到的值为123qwe




原文地址:访问原文地址
快照地址: 访问文章快照