zoukankan      html  css  js  c++  java
  • 正则表达式的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+(?!€)/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确保了字符串数量正确。


  • 相关阅读:
    win查看所有wifi密码
    vsftp配置详解
    python3.7项目打包为一个exe
    ATT&CK实战系列——红队实战(一)
    PHP SECURITY CALENDAR 2017 (Day 9
    python3安装gmpy2
    [CISCN2019 总决赛 Day2 Web1]Easyweb(预期解)
    python2与python3共存及py2IDLE打不开的解决方案
    [BJDCTF 2nd]
    PHP SECURITY CALENDAR 2017 (Day 1
  • 原文地址:https://www.cnblogs.com/mosakashaka/p/14677952.html
Copyright © 2011-2022 走看看