热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

正则匹配到第二个_JavaScript正则表达式迷你书(读书笔记)

1.正则表达式字符匹配攻略:要么匹配字符,要么匹配位置两种模糊匹配:横向模糊和纵向模糊1.1.横向模糊匹配:一个正则可匹配的

1. 正则表达式字符匹配攻略:要么匹配字符,要么匹配位置

两种模糊匹配:横向模糊和纵向模糊

1.1. 横向模糊匹配:一个正则可匹配的字符串的长度不是固定的,可以是多种情况的

  • 其实现的方式是使用量词。譬如 {m,n},表示连续出现最少 m 次,最多 n 次。
  • eg: 比如正则 /ab{2,5}c/ 表示匹配这样一个字符串:第一个字符是 "a",接下来是 2 到 5 个字符 "b",最后是字符 "c"。其可视化和测试如下:
dd9030849a57d725d7c6b7c1b8459fc8.png
71434e5f61d9e31896e8b5ab0788d985.png

1.2. 纵向模糊匹配: 一个正则匹配的字符串,具体到某一位字符时,它可以不是某个确定的字符,可以有多种可能

  • 其实现的方式是使用字符组。譬如 [abc],表示该字符是可以字符 "a"、"b"、"c" 中的任何一个。
  • 比如 /a[123]b/ 可以匹配如下三种字符串: "a1b"、"a2b"、"a3b"。
c1f5b91649a0937ce9b0cfc768f165b6.png
2f7686b2ea2c41882f38812b6c86eb24.png
字符组

1.3. 范围表示法

  • 比如 [123456abcdefGHIJKLM],可以写成 [1-6a-fG-M]。用连字符 - 来省略和简写。
  • 需要注意的是,连字符有特殊用途,如果匹配"a"、"-"、"z"中的任意一个,不能写成[a-z],可以写成:[-az]、[za-]、[a-z]。

1.4. 排除字符法

  • 其实现的方式是使用反义字符组。譬如 [^abc],表示该字符是排除字符 "a"、"b"、"c" 之外的任意字符。

1.5. 常见的简写形式

  • 有了字符组概念,一些常见的符号就好理解了,系统提供了自带的简写方式
92f180e40a0bfcd85644a9cb305ad75b.png
dd23668282ea8f3daa93390dd8a97b51.png
  • 量词的简写形式
b7d004ce3aa283438a15b540f6b5f6e5.png
81900232f93f818d01116db54b7913cb.png
贪恋匹配和惰性匹配

1.6. 贪婪匹配

  • 正则 /d{2,5}/,表示数字连续出现 2 到 5 次。会匹配 2 位、3 位、4 位、5 位连续数字。但是其是贪婪的,它会尽可能多的匹配。只要在能力范围内,越多越好。

1.7. 惰性匹配

  • 正则 /d{2,5}?/ 表示,虽然 2 到 5 次都行,当 2 个就够的时候,就不再往下尝试了。通过在量词后面加个问号就能实现惰性匹配。
4b6af55b41204ab0af5e04cf4890427e.png

1.8. 多选分支

  • 一个模式可以实现横向和总想模糊匹配,而多选分之可以支持多个自模式任选其一
  • 具体形式:(p1|p2|p3),其中 p1、p2 和 p3 是子模式,用 |(管道符)分隔,表示其中任何之一
  • 需要注意的是,分之匹配是惰性的,比如我用 /good|goodbye/,去匹配 "goodbye" 字符串时,结果是 "good"。
958ddba11b247b1abecc011ca07f6296.png

2. 正则表达式位置匹配攻略:位置(锚)是相邻字符之间的位置

如何匹配位置,在 ES5 中有 6 个锚:^、$、b、B、(?=p)、(?!p)
  • ^(脱字符)匹配开头,在多行匹配中匹配行开头。
  • $(美元符号)匹配结尾,在多行匹配中匹配行结尾。
  • b 是单词边界,具体就是 w 与 W 之间的位置,也包括 w 与 ^ 之间的位置,和 w 与 $ 之间的位置。
  • B 就是 b 的反面的意思,非单词边界。例如在字符串中所有位置中,扣掉 b,剩下的都是 B 的。
  • (?=p),其中 p 是一个子模式,即 p 前面的位置,或者说,该位置后面的字符要匹配 p。
8d97ce1d6cad5f5c708d373e02142ec5.png
  • 而 (?!p) 就是 (?=p) 的反面意思
7bab9bf20c8044479ef836a5c5d4e550.png
f9a436396ad89a46a8e787b7f87e874d.png

3. 正则表达式括号的作用:分组和分支是括号最直觉的作用

分组

3.1. 我们知道 /a+/ 匹配连续出现的 "a",而要匹配连续出现的 "ab" 时,需要使用 /(ab)+/。其中括号是提供分组功能。

分支结构

3.2. 而在多选分支结构 (p1|p2) 中,此处括号的作用也是不言而喻的,提供了分支表达式的所有可能。

分组引用

3.3. 如:/d{4}-d{2}-d{2}/ 和 /(d{4})-(d{2})-(d{2})/; 后者多了分组的编号。

  • 搭配合理的 API,实现更强大的操作。如下可视化正则,多了分组引用的概念
1622c3359ea633e8f457474d081839c6.png
反向引用

3.4. 除了使用相应的 API 来引用分组,也可以在正则本身里引用分组,但只能引用之前出现的分组,即为反向引用。

  • 如匹配前后分隔符一致的日期"2017-06-12",可以使用正则 /d{4}(-|/|.)d{2}1d{2}/;其中里面的 1,表示的引用之前的那个分组 (-|/|.)。那么2 和 3 自然理解了,表示第二个和第三个分组。
  • 那么 10 表示第十个分组,还是表示1 和 0 呢? 答案是前者,如果要表示后者,请使用(?:1)0 或者 1(?:0)
d6d7fb3a8413db88e0ff57ad482dd59b.png
40d095e3ada72292f7e89913c994097d.png
  • 引用不存在的分组,正则匹配时不会报错,只是匹配反向引用的字符本身。
  • 分组后面有量词,分组最终捕获的是最后一次的匹配。

3.5. 非捕获括号

    • 上文提到的括号,都会匹配他们捕获到的数据,以便后续作为引用,成为捕获型分组或分支。如果想要括号原始功能,此时应使用非捕获括号(?:p) 或 (?:p1|p2|p3)

4. 正则表达式回溯法原理

回溯匹配的概念

4.1. 没有回溯的匹配

  • 例如正则是/ab{1,2}c/,如果目标字符串是“abbbc”,其匹配就是没有回溯的,其匹配过程如下:
c9fb3a653835b6add2c71260b37ac7a9.png
8c2561c2f8bcb62643783cac738b09b1.png

4.2. 有回溯的匹配

  • 如上正则,如果目标字符串是“abbc”,其匹配就是有回溯的,其匹配过程如下,其第6步就是回溯:
ba3bbe875438c94de7c5beec259e05bf.png
贪婪量词和惰性量词

4.3. 贪婪量词

  • 比如 b{1,3},因为其是贪婪的,尝试可能的顺序是从多往少的方向去尝试。首先会尝试 "bbb",然后再看整个正则是否能匹配。不能匹配时,吐出一个 "b",即在 "bb" 的基础上,再继续尝试。如果还不行,再吐出一个,再试。如果还不行呢?只能说明匹配失败了。
3b1b4347c1e516d0e270960b03b65c80.png

4.4. 惰性量词

  • 惰性量词就是在贪婪量词后面加个问号。表示尽可能少的匹配。

5. 正则表达式的拆分

正则表达式有哪些结构?

5.1. 字符字面量、字符组、量词、锚、分组、选择分支、反向引用,

  • 具体含义如下:
e950c8890bd14e6bff588416d88464ae.png
  • 涉及到的操作符有:
1017692d80fd3805f237d33a9986a29d.png
  • 尝试拆分一个正则:/ab?(c|de*)+|fg/
    • 由于括号的存在,所以(c|de*)是一个整体
    • 而(c|de)存在一个量词,所以 e是一个整体
    • 而分支结构|优先级较低,所以 c 是一个整体,de*是一个整体

最终被拆分为 a、b?、(…)+ 和 f、g 两个部分

量词连缀问题
  • 如果匹配每个字符为‘a’,‘b’,‘c’任意一个,字符串长度是 3 的倍数,如果正则想当然地写成 /^[abc]{3}+$/,这样会报错,说 + 前面没什么可重复的。而要修改为:
fd775802317eab252c1ad0668560bc6e.png
元字符转译问题

5.2. 所谓元字符,就是正则中有特殊含义的字符:^、$、.、*、+、?、|、、/、(、)、[、]、{、}、=、!、:、- ,

  • 如果要使用这些元字符,需要对其转义,但并不是所有的字符都需要转义
  • 在字符组中的元字符,比如匹配 "[abc]" 和 "{3,5}",可以写成/[abc]/ 或 /[abc]/,/{3,5}/ 或 /{3,5}/
  • 其余情况,比如 =、!、:、-、, 等符号,只要不在特殊结构中,并不需要转义;括号需要前后都转义的;于剩下的 ^、$、.、*、+、?、|、、/ 等字符,只要不在字符组内,都需要转义的。

6. 正则表达式的构建和编程

平衡法则
  • 匹配预期的字符串
  • 不匹配非预期字符串
  • 可读性和可维护性
  • 效率
正则表达式相关 API

6.1. 用于正则操作的方法,共有 6 个,字符串实例 4 个,正则实例 2 个:

6c182f21e4306dee223d6e01722355b7.png

6.2. search 和 match 参数问题,会把参数 string 转为 regexp。

6.3. match 返回结果的格式,与正则对象时候有修饰符 g 有关。没有 g,返回标准格式;有 g,返回所有匹配内容

ba3bc9629492ab88a7fc042a56d716a4.png

6.4. exec 比 match 强大,exec 作为对 match 含有 g 匹配内容的补充,包含所有匹配内容的 index 信息

6.5. g 对 exec 和 test 的影响,对于字符串的四个方法,都是从 0 开始的,lastIndex 属性始终保持不变。而对于正则的两个方法,lastIndex 会受 g 的影响

    • 注意下面代码中的第三次调用 test,因为这一次尝试匹配,开始从下标 lastIndex,即 3 位置处开始查找,自然就找不到了。
0aa9269e02b76b91b593530b1cdc0d74.png
    • 如果没有 g,都是从字符串第 0 个位置开始尝试匹配
8cbbc5dcb74d10403e13fe2bfd3492d1.png

6.6. test 整体匹配时需要使用 ^ 和 $

6.7. replace 是很强大的。总体来说 replace 有两种使用形式,这是因为它的第二个参数,可以是字符串,也可以是函数。

    • 当第二个参数是字符串时,如下的字符有特殊的含义:
fba17b3ac7fa31642a4d67bd5c90bee1.png

6.8. 正则表达式 ES5 有 3 个修饰符

55eb4ced3f2d4bec93aaabff22a66e22.png



推荐阅读
author-avatar
啊啦哈200601
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有