最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 三十分钟包会——正则表达式

    正文概述 掘金(就那)   2021-03-16   448

    一、前言

    正则表达式,对大家来说既熟悉又陌生。熟悉是因为工作中有很多场景能用到,比如手机号、邮箱、密码等规则校验。

    陌生则是因为正则表达式看上去就是一堆乱码,且一眼看上去很难看懂匹配规则。有时候在网上去找一个特定规则的正则表达式,搜出来的结果各不相同,执行效果更是不尽人意,想自己去修改,感觉也无从下手。

    今天就花费30分钟时间,带领大家从另一个角度去剖析匹配的目的,理解匹配的思路,一步一步抽丝剥茧去学会怎么写正则表达式(读正则表达式远比写表达式要困难)。

    二、理解正则要干的事情

    正则要干的事情,可以总结为以下灵魂三问:

    Q1、匹配啥?
    Q2、匹配不是啥?
    Q3、匹配多少次?

    Q1、匹配啥?

    这个比较好理解,比如想匹配字符a,那就直接写/a/,只要字符串某个位置是a就可以匹配上:

    /a/.test("javascript") //true
    

    匹配以a开头的字符串,就加上元字符^(开始位置标识),/^a/

    /^a/.test("javascript") //不是以a开头返回false
    /^a/.test("abc") //是以a开头返回true
    

    匹配以a结尾的字符串,就加上元字符$(结束位置标识),/a$/

    /a$/.test("javascript") //不是以a结尾返回false
    /a$/.test("cba") //是以a结尾返回true
    

    匹配字符a或b,可以把对应的字符放入中括号里/[ab]/,只要字符串包含a或者b就可以匹配上:

    /[ab]/.test("byte") //true
    

    匹配字符串abc或xyz,/abc|xyz/

    /abc|xyz/.test("aabbxyz") //本字符串包含xyz,所以返回true
    

    ① 匹配某表达式前面的(前瞻)

    exp1(?=exp2):匹配exp2前面的exp1,匹配结果不包含exp2

    比如要匹配字符串中script前面的部分java, /java(?=script)/

    /java(?=script)/.test("javascript,javaee,typescript") //字符串中javascript符合规则 会返回ture
    
    //1、用exec方法来验证下匹配的结果
    /java(?=script)/.exec("javascript,javaee,typescript")
    //2、得到匹配结果如下:
    ["java", index: 0, input: "javascript,javaee,typescript", groups: undefined]
    //3、会发现匹配到的是java,index是0,说明找到了的是javascript中script前面的java
    

    ② 匹配某表达式后面的(后顾)

    (?<=exp2)exp1:匹配exp2后面的exp1,匹配结果不包含exp2

    比如要匹配字符串中java后面的部分ee, /java(?>=ee)/

    /(?<=java)ee/.test("javascript,javaee,typescript") //字符串中javaee符合规则 会返回ture
    
    //1、用exec方法来验证下匹配的结果
    /(?<=java)ee/.exec("javascript,javaee,typescript") 
    //2、得到匹配结果如下:
    ["ee", index: 15, input: "javascript,javaee,typescript", groups: undefined]
    //3、会发现匹配到的是ee,index是15,说明找到了的是javaee中java后面的ee
    

    Q2、匹配不是啥?

    匹配不是啥,意思就是取反,只要不是这些的都可以匹配,比如不想匹配字符a,正则写法为/[^a]/,是在中括号里面加上元字符^,这样只要字符串满足有不是这个集合里面的字符,都可以被匹配上:

    /[^a]/.test("aaa") //字符串全是a,返回false
    /[^a]/.test("abc") //字符串不全是a,返回true
    

    匹配不是以a开头的,跟之前匹配啥类似,加上元字符/^[^a]/

    /^[^a]/.test("javascript") //此字符串不是以a开头,返回true
    /^[^a]/.test("abc") //此字符串是以a开头,返回false
    

    匹配不是以a结束的,也跟之前匹配啥类似,加上元字符/[^a]$/

    /[^a]$/.test("javascript") //此字符串不是以a结束,返回true
    /[^a]$/.test("cba") //此字符串是以a结束,返回false
    

    不匹配字符a、b、c,可以把对应的字符都放入中括号里/[^abc]/

    /[^abc]$/.test("abccba") //此字符串的字符全部都不符合,返回false
    

    ① 匹配后面不是某表达式的(负前瞻)

    exp1(?!exp2):匹配后面不是exp2的exp1,匹配结果不包含exp2

    比如要匹配字符串中后面不是script的java, /java(?!script)/

    /java(?!script)/.test("javascript,javaee,typescript") //字符串javaee符合规则 会返回ture
    
    //1、用exec方法来验证下匹配的结果
    /java(?!script)/.exec("javascript,javaee,typescript")
    //2、得到匹配结果如下:
    ["java", index: 11, input: "javascript,javaee,typescript", groups: undefined]
    //3、会发现匹配到的是java,index是11,说明找到了的是javaee中的java,因为这个java后面是ee
    

    ② 匹配前面不是某表达式的(负后顾)

    (?<!exp2)exp1:匹配前面不是exp2的exp1,匹配结果不包含exp2

    比如要匹配字符串中前面不是java的script,/(?<!java)script/

    /(?<!java)script/.test("javascript,javaee,typescript") //字符串中typescript符合规则 会返回ture
    
    //1、用exec方法来验证下匹配的结果
    /(?<!java)script/.exec("javascript,javaee,typescript")
    //2、得到匹配结果如下:
    ["script", index: 22, input: "javascript,javaee,typescript", groups: undefined]
    //3、会发现匹配到的是script,index是22,说明找到了的是typescript中type后面的script
    

    ③ 不匹配包含abc的字符串

    这是一个比较特殊的匹配行为,如果只是写成/[^abc]/的话,这只意味着字符串不能全是由a、b、c这三个组成的,跟需求不匹配。

    那我们要从另外一个角度去分析,字符串的任意一个位置开始都不能连续出现abc,我们可以利用负前瞻来实现:

    1. 位置后面都不能是abc,使用负前瞻匹配空位置:/(?!abc)/
    2. 从开始到结束每个位置都要覆盖到,添加开始结束标记:/^(?!abc)/$
    3. 这个位置后面可以是其他的字符,用\w来表示:/^(?!abc)\w$/
    4. 满足上面情况后的位置,可以连续出现多个,用+来表示数量:/^((?!abc)\w)+$/
    /^((?!abc)\w)+$/.test("cbacbac") //本字符串中不包含连续的abc,结果返回true
    /^((?!abc)\w)+$/.test("cbacbabc") //本字符串中包含连续的abc,结果返回false
    

    Q3、匹配多少次?

    匹配一次可以什么都不用定义,比如匹配一个数字/\d/,如果要匹配连续三个数字最简单的方式就是连续写三次:/\d\d\d/,这样写本身是没有问题的,能正确匹配。

    但是如果次数太多或者次数不确定,这么写肯定不行,所以可以加上长度规则:

    *:匹配任意次

    +:最低匹配1次

    ?:匹配1次或者0次

    {m}:匹配m次

    {m,}:最低匹配m次

    {m,n}:最低匹配m次,最多匹配n次,m需要小于等于n

    正则默认是贪婪匹配,就是符合条件的会一直匹配,如果想阻止贪婪匹配,可以在长度规则后面加一个?,比如:

    /\d{2,}/.exec("1234567890")
    //得到匹配结果如下,会匹配到所有数字:
    ["1234567890", index: 0, input: "1234567890", groups: undefined]
    
    //1、添加?,阻止非贪婪匹配后
    /\d{2,}?/.exec("1234567890")
    //2、得到匹配结果如下,只会匹配2个数字:
    ["12", index: 0, input: "1234567890", groups: undefined]
    

    ① 使用分组

    如果想匹配多次某个单词如regregregregregreg时候怎么办,我们看到reg连续出现了6次,如果傻傻的把6个reg写在了正则表达式中肯定不合适,我们就可以利用分组来实现,我们把reg放在括号里面,然后让这个分组重复6次,/(reg){6}/

    /(reg){6}/.test("regregregregregreg") //匹配成功,返回true
    

    不过这样利用分组是有个前提,就是知道要匹配的字符串就是reg,然后重复这个分组。如果想匹配类似8899或者5522这种重叠类型的字符怎么办呢?那我们可以把重叠的第一个放入分组,再使用这个分组匹配下一个:

    /(\d)\1(\d)\2/.exec("2345566789")
    //得到匹配结果如下,返回了5566,分组对应的5、6也被返回
    ["5566", "5", "6", index: 3, input: "2345566789", groups: undefined]
    

    ② 分组捕获

    默认的分组是可以被捕获的,上面的\1\2是在正则表达式内部捕获的分组。如果想在外部去捕获分组匹配的数据可以使用RegExp.$1-$9来获取。只要正则匹配了就会有。可以使用testexec或者str的replace方法来获取$1-$9

    使用test:

    /([a-z]{2})(\d{2})/.test("xyz123")
    RegExp.$1 //返回第一个分组表达式匹配到的内容 yz
    RegExp.$2 //返回第二个分组表达式匹配到的内容 12
    

    使用replace:

    "xyz123".replace(/([a-z]{2})(\d{2})/,'$2$1')
    //会返回结果:x12yz3,就是把第一个分组匹配到的内容yz和第二个分组匹配到的内容12互换了
    

    ③ 分组不捕获

    如果不想捕获分组,只需要在分组内加上?:就可以了

    /([a-z]{2})(?:\d{2})/.test("xyz123")
    RegExp.$1 //返回第一个分组表达式匹配到的内容 yz
    RegExp.$2 //分组未被捕获 返回空字符串
    

    三、总结

    本文不去赘述元字符的含义以及组合使用方法,这些是需要记死背硬的东西。而是教给大家一种如何切入正则表达式的思维,怎么去一步步分析要匹配的需求,把长的、复杂的需求拆成短的、简单的,正向不行的就逆向去分析,一点一点去组合,然后回归灵魂三问:匹配啥?匹配不是啥?匹配多少次? ,去完成符合要求的正则表达式。


    起源地下载网 » 三十分钟包会——正则表达式

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元