正则表达式案例分析 (二)

前言

最近在重新学习正则表达式,把在学习过程中所遇到的案例,还有比较难理解概念用自己的理解分析并整理总结。

如有哪些地方不对,欢迎指正,谢谢!(๑•ᴗ•๑)

本系列使用的JavaScript所支持的正则表达式语法,并推荐你使用 regexr.com/ 去做相应的练习。

假定你已经熟悉元字符方括号修饰符,量词RegExp对象

如果没有,请先看一遍文档
www.w3school.com.cn/jsref/jsref…

本系列同步GitHub github.com/Janking/Blo…

系列目录

正则表达式案例分析 (一)

案例分析

(1) 重复分组

在上一篇介绍千分位的时候,就有用到重复分组,这是一个很容易理解错误的点,至少我开始的时候是理解错误的。

https://user-gold-cdn.xitu.io/2017/7/23/0752787423b4fe0c5aaa52f2126294ba

假定用这个正则去匹配 1234567890,开始我以为分组小括号(\d\d\d)的最终结果是 123456789都能拿到,但结果却只有789

重复分组的匹配在每次引擎退出该分组的时候被捕获,并会覆盖该分组在之前匹配的任何文本

模拟一下引擎工作的步骤:

1. 第一次匹配,捕获到 `123`,退出分组
2. 第二次匹配,捕获到 `456`, 覆盖上一次捕获的`123`,退出分组
3. 第三次匹配,捕获到 `789`,覆盖上一次捕获的`456`,退出分组
4. 退出重复分组,结束复制代码

因为重复分组最后一次循环存储的是789,另外两次分组匹配,也就是123,456是无法被获取的。

如果想要获得所有结果,就要把重复匹配放进分组中 /((\d\d\d){3})/

(2) 获取<p>...</p>中的内容

https://user-gold-cdn.xitu.io/2017/7/23/92b63477e6366c36f7dac825f3bda438

/<p>(.*?)<\/p>/g.exec('<p>Hello,<em>world</em></p><p>Hello,Janking</p>')

运行结果
[
    "<p>Hello,<em>world</em></p>",
     "Hello,<em>world</em>", 
     index: 0, 
     input: "<p>Hello,<em>world</em></p><p>Hello,Janking</p>"
]复制代码

假如没有?,而匹配结果就会差很远,不信你看!

/<p>(.*)<\/p>/g.exec('<p>Hello,<em>world</em></p><p>Hello,Janking</p>')

运行结果
[
    "<p>Hello,<em>world</em></p><p>Hello,Janking</p>", 
    "Hello,<em>world</em></p><p>Hello,Janking", 
    index: 0, 
    input: "<p>Hello,<em>world</em></p><p>Hello,Janking</p>"
]复制代码

缺少了问号?,结果把中间的</p><p>也匹配进来了,为什么一个字符不同,匹配结果就差异那么大?这里涉及到正则表达式中比较重要的概念:贪婪匹配,懒惰匹配,回溯

贪婪匹配

属于贪婪模式的量词,也叫做匹配优先量词,包括:{m,n}{m,}?*+

惰性匹配

在匹配优先量词后加上?,即变成属于惰性匹配的量词,也叫做忽略优先量词,包括:{m,n}?{m,}???*?+?

回溯

当前前面分支/重复匹配成功后,没有多余的文本可被正则后半部分匹配时,会产生回溯

用一个简单的例子来解释一下贪婪匹配和惰性匹配!

贪婪 : /\d+\b/

惰性 : /d+?\b/

文本 : 1234a

贪婪正则匹配 1234a 时的过程是这样的:

    1. \d+ 匹配得到 1234
    2. \b  却匹配失败,因为它的左边必须是数字,而不是字母 (\b 是分词边界匹配,用来获取位置,而不是文本,上一节有讲到)
    4. 这个时候,\d+会尝试回吐一个字符,即匹配结果为 123 ,可\b还是匹配失败!
    5. 那就继续回吐,一直到 1,还是匹配失败,那么这个正则就整体匹配失败了
    6. 这个回吐匹配结果的过程就是回溯复制代码

惰性正则匹配 1234a 时的过程是这样的:

    1. \d+? 首先匹配,结果是 1 ,紧接着 \b 匹配失败
    2. 那就 \d+? 继续匹配,结果是 12 ,紧接着 \b 还是匹配失败
    3. \d+? 一直匹配到1234,紧接着的 \b 依然匹配失败
    4. 结果整个正则匹配不成功复制代码

通过这两个例子的比较,相信你会猜到回溯会影响匹配速度,回溯的过程慢那是相对那些DFA引擎。

而JS的正则引擎是NFA(非确定型有限自动机),匹配慢,编译快。

结束语

本章节将的案例只有两个,主要是涉及到几个重要概念,占了一定的篇幅,由于本人不喜欢把文章写的太长,影响阅读体验,所以就此打住,从下一篇开始会重点的去分析常用正则表达式的匹配过程,敬请期待。

参考文献:

  • 《精通正则表达式》
  • 《正则表达式经典实例》

转载于:https://juejin.im/post/5973f16c51882573c14a812d

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值