正则表达式的lookaround(lookahead/lookbehind)以及密码复杂度检查

前言

密码复杂度校验是很常见的功能,一般用正则实现。
网上搜索到的内容,使用了正则的Lookaround表达式,之前没有用过,这里记录一下

Lookaround

主要的内容来自这里,讲的很通俗易懂。这里做一下简单的翻译

Lookaround包括LookaheadLookbehind两种匹配模式。

功能解释

有时候我们需要匹配一段文本,但是只有当这段文本有特定的前缀 或者后缀时才匹配到他

比如1 turkey costs 30€,我们想获得这里的价格30,这个数字的特点是,他有一个后缀

这时候就可以用Lookahead

Lookahead

Lookahead的语法是X(?=Y),它的意思是,查询X,但是仅当X的后面跟的是Y

当然,这里的XY都可以是正则表达式的匹配模式

以前面的需求为例,需要查询一个有后缀的数字,那么相应的正则表达式是\d+(?=€)

let str = "1 turkey costs 30€";
alert( str.match(/\d+(?=€)/) ); //30

需要注意的是Lookahead语法匹配的后缀仅仅是检测使用,不会在返回结果(30)中

Lookahead还可以支持更复杂的场景,比如X(?=Y)(?=Z),它的含义是:

  1. 找到X
  2. 校验Y是否紧跟X(否则丢弃)
  3. 校验Z是否紧跟X(否则丢弃)
  4. 如果2和3都匹配,则X匹配,否则继续搜索

这种情况下,YZ不能是互斥的

举个例子,\d+(?=\s)(?=.*30),这里查找一个数字,这个数字后面紧跟一个空格,并且在这个数字后面的某个地方,有一个数字30``(?=.*30):

let str = "1 turkey costs 30€";

alert( str.match(/\d+(?=\s)(?=.*30)/) ); // 1

Negative Lookahead

如果我们想找一个数字,他后面不是符号呢?这时候可以用Negative Lookahead模式:X(?!Y)

它的意思是,寻找X,但是仅当X的后面不是Y的时候

let str = "2 turkeys cost 60€";

alert( str.match(/\d+\b(?!€)/g) ); // 2

Lookbehind

Lookahead检测的是后缀,而Lookbehind检测的是前缀。

Lookahead类似,Lookbehind也有Positive、Negative两种匹配方式:

  • Positive lookbehind: (?<=Y)X, 仅当X前面是Y时匹配成功
  • Negative lookbehind: (?<!Y)X, 仅当X前面不是Y时匹配成功

还是用之前的例子,把单位换成人民币,这时候我们想要匹配¥30,需要使用(?<=¥)\d+,匹配一个前缀是的数字:

let str = "1 turkey costs ¥30";

alert( str.match(/(?<=¥)\d+/) ); // 30 

如果想要匹配数量,即没有前缀的数字,而非价格,那么可以使用(?<!\$)\d+

捕获组(Capturing Group)

之前提到一点,无论是Lookaround还是Lookbehind,匹配的内容都不包含前缀和后缀本身。

比如对于这个模式\d+(?=€)就不在最后的结果当中。

如果想要在结果中添加,那么可以用括号把需要匹配的内容包括起来。

在下面这个例子里(€|kr)就会和价格的数字一起返回:

let str = "1 turkey costs 30€";
let regexp = /\d+(?=(€|kr))/; // €|kr周围加了括号

alert( str.match(regexp) ); // 30, €+

关于密码复杂度验证

回到最开始的目的,密码复杂度校验。要求是8~20位,包含字母、数字和特殊字符。

网上很容易搜到解决方案:^(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[._~!@#$^&*])[A-Za-z0-9._~!@#$^&*]{8,20}$

整个表达式可以分为4部分

  1. ^(?=.*[a-zA-Z])
  2. ^(?=.*[0-9]) 注意这里开头的^就是前面提到的级联的用法,虽然^不在这个表达式之前,但是匹配时也是这样检测的。
  3. ^(?=.*[._~!@#$^&*])
  4. [A-Za-z0-9._~!@#$^&*]{8,20}

其中1-3分别用来匹配字母、数字、特殊字符,这里用到的是Lookahead后缀匹配,而匹配的内容是^既字符串的开头。

所以1-3确保了不同类型字符串存在,4确保了字符串数量正确。


posted @ 2021-04-19 17:58  mosakashaka  阅读(414)  评论(0编辑  收藏  举报