[TOC]

写在前面 - Lionad

正在看VueJS的源码, 看到了HtmlParser部分, 感觉以前看的正则表达式基础知识已经完全不够用了, 现翻阅博客资料, 将一些JS中正则表达式难用的部分总结归纳, 方便自己和sf友翻阅.

正则分组

重复匹配

对于重复的匹配, 我们经常使用到正则表达式的分组功能, 我们使用正则匹配IP地址来实践一下.

假设我们要匹配的IP地址在区间 0.0.0.0 - 255.255.255.255 之间, 可以直观的了解到, 我们只需要匹配 三位数字+点号 三遍, 再匹配三位数字一遍就可以了.

这里说的 三位数字+点号 既是我们说的一种规则, 我们可以在表达式中将它们转化为规则即: \d{1,3}\., 当我们把规则用括号包装后, 就变成了组: (\d{1,3}\.), 所以匹配IP地址的正则表达式可以写作: (\d{1,3}\.){3}\d{1,3}

换种思路, 我们也可以这样匹配: \d{1,3}(\.\d{1,3}){3}

拓展: 聪明的你可能已经想到, \d{1,3} 匹配是有疏漏的. 在实际生产过程中, \d{1,3} 可能匹配 999 这种数字, 他是一个错误的IP地址段. 这里贴上真实的IP地址正则匹配供大家参考: ((25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d))) , 另人愉快的是, 它使用的分组策略仍然是不变的.

后向引用(反向引用)

我们考虑一个很特殊的情况, 当我们要匹配四个IP段相同的情况, 如 100.100.100.100 时, 重复匹配分组的策略失效了: 重复匹配分组 并不能保证匹配相同的数字 -> 这时候我们需要借助 后向引用 策略的力量了(少年, 你渴望力量吗2333, 戳我头像, 带你探索音乐与代码交织的文艺道路.)

后向引用在不同语言的正则表达式书写中, 有不同的语法, 我们讨论JS中最常见的一种, 形如: \number 的后向引用, 其中, number 代表分组的序号.

给你一个简单的栗子, 瞬间就记住了, 假使我们要匹配重复的三位数字, 我们将匹配一个数字的规则标记为一个分组: (\d), 重复匹配这个分组(第一个分组)的具体内容三次: (\d)\1, 这样就达到了目的.

我们很容易将重复匹配和后向引用分别开来: 前者是重复匹配相同的规则, 后者是匹配分组的具体内容.

默认的一些规则需要稍加理解并记住:

  • \0代表的是, 整个正则表达式的匹配的内容

捕获分组与不捕获分组

当我们用括号包装一个规则, 即造了一个分组, 这个分组是默认被捕获的, 也就是说, 我们能利用后向引用等手段(\number)去调用这个分组.

但是如果我们不想保存这个分组的结果到索引中, 便可以使用形如(?:)的不捕获分组, 表示不需要暂存此分组.

正则断言

还记得我看过的一篇大概名为<30分钟学会正则表达式>的文章中, 里面提及过正则断言.
当时感觉真是一看就懂. 但很遗憾, 实际生产中, 使用各种复杂正则表达式的情况实在是太少, 今天如果不翻阅百度, 我恐怕是不能记起断言的分类和各种使用方法了.

断言的字面意思便是, 断定(程序)运行到此时(结果)是这样的"场景", 它描述的是一种 场景, 换句话说, 是一种"肯定的场景". 但要记住的是, 我们的"结果"是不包含在"场景"里面的.

VueJS里头需要匹配HTML tag, 我们就以匹配: '<segment>Not Fault</segment>' 中的 'Not Fault' 为例吧.

我们如果使用普通的正则表达式, 如 /<segment>.*</segment>/ 会匹配到整个字符串 '<segment>Not Fault</segment>'. 我们使用断言, 以"场景"的方式思考: '<segment>' 和 '</segment>' 是一种"肯定的场景", 我们需要匹配的结果是: 'Not Fault', 无论tag内部的字符无论如何变化, tag头和tag尾都是不变的.

一鼓作气, 我们继续往下

先行断言

先行断言, 我是这样理解的: 先匹配内容, 再做"场景"假设.

放到我们先前的栗子中, 便这样匹配, 一直匹配内容, 直到碰上 '</segment>' 的场景, 语法如下: (?=</segment>)

后发断言

后发断言, 我的理解是: 先匹配场景, 再匹配内容.

放到我们先前的栗子中, 先匹配 '<segment>' 的场景, 再继续往下匹配内容, 语法如下: (?<=<segment>)

实践

正则表达式是对字符串内容做匹配, 所以我将"先"和"后"的理解绑定到内容匹配的先后顺序上, 方便理解.

我们将先行断言和后发断言结合起来, 整个表达式如下: (?<=<segment>).*(?=</segment>), 我们便可获得想要的结果: 'Not Fault' 了.

"正负"断言

其实我们刚才做的是肯定的场景, 实际情况中还有"不满足此场景"的使用场景.

比如, 我们刚才使用的表达式: (?<=<segment>).*(?=</segment>) 是肯定有 '<segment>' '</segment>' 的场景下去匹配内容, 其实是使用的 "正后发断言" 和 "正先行断言", "正"即代表肯定的状态.

那负断言, 也就是不满足场景的断言咯... 语法即把正断言中的等于号换成感叹号:

  • 负先行断言 (?!)
  • 负后发断言 (?<!)

如: ['1999','2099','2199'...'9099'] 中如果我们要匹配除了'1999'以外的所有带有'99'结尾的年份, 我们可以使用表达式: (?<!19)99

拓展: JS中是不支持后发断言的, 所以嘛... 没什么所以, 因为至少还没碰到过缺少后发断言就解决不了的问题2333

后记

网易云 Lionad_Guirotar : 前端新手一枚, 欢迎各位 加油&吐槽. 戳我头像, 带你探索音乐与代码交织的文艺道路.

参考文章&相关阅读

  • JS捕获分组于不捕获分组 https://www.zhihu.com/questio...
  • JS正则基础 http://blog.sina.com.cn/s/blo...
  • JS后发断言 https://www.cnblogs.com/pmars...
  • JS没有后发断言的解决方案 https://segmentfault.com/q/10...
  • JS分组&断言 https://www.cnblogs.com/iyang...

『不再迷茫 - 正则表达式』JS正则要点梳理 持续更新相关推荐

  1. 『正则表达式』《正则指引》学习笔记

    文章目录 1. 字符组 1.1 普通字符组 1.2 元字符与转义 1.3 排除型字符组 1.4 字符组简记法 1.5 匹配范围 2. 量词 2.1 一般形式 2.2 常用量词 2.2.1 量词?的应用 ...

  2. Javascript正则表达式,Js正则大全

    不保证全部使用无误, 有效性,请自行测验! 一.校验数字的表达式 数字:^[0-9]*$ n位的数字:^\d{n}$ 至少n位的数字:^\d{n,}$ m-n位的数字:^\d{m,n}$ 零和非零开头 ...

  3. JS逆向学习笔记 - 持续更新中

    JS逆向学习笔记 寻找深圳爬虫工作,微信:cjh-18888 文章目录 JS逆向学习笔记 一. JS Hook 1. JS HOOK 原理和作用 原理:替换原来的方法. (好像写了句废话) 作用: 可 ...

  4. 我的js函数库(持续更新)

    常用js初始化函数 function id(obj) {return document.getElementById(obj); } function bind(obj, ev, fn) { if ( ...

  5. 常用html/css/js学习(会持续更新)

    html5 前端三要素: js 动化(能说会道 会交流) css 美化(妆容) html 结构(身材) html5 超文本标记语言解释型标签语言 运行机制?1) 开发pc - 部署pc - pc-浏览 ...

  6. 2022年js基础面试题---持续更新

    目录 1.javascipt的数据类型 1.1基本类型 1.2引用类型 1.3存储方式的区别 1.4 undefined和null的区别 1.5JavaScript什么情况下会返回undefined值 ...

  7. js面试题(持续更新)

    js面试题 new操作符具体干了什么 创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型 属性和方法被加入到 this 引用的对象中 新创建的对象由 this 所引用,并且最后隐 ...

  8. html css js知识整理,Html+Css+Js实用知识汇总(持续更新中...)

    Html篇 基本概念: html:超文本标记语言(Hyper Text Markup Language) html5:下一代的html xhtml:更严谨更纯净的html 表头 网站标题 //页面编码 ...

  9. Node.js零基础自学(持续更新中)

    1. Node.js时基于Chrome V8 引擎的JavaScript运行环境.官网:Node.jsNode.js® is a JavaScript runtime built on Chrome' ...

最新文章

  1. SQL创建linkserver
  2. GPIO模拟I2C程序实现
  3. 1099 字串变换 2002年NOIP全国联赛提高组
  4. X大佬:建议被降级降薪员工主动辞职,网友炸了
  5. 漫画:什么是字符串匹配算法?
  6. centos怎么编写java_编写的java程序在centos后台运行的方法
  7. fisco bcos应用开发(一) springboot报错 Error reading resource
  8. 递归求n的阶乘不溢出_面试官:说一说递归如何优化尾递归优化
  9. PanDownload复活了!60MB/s!
  10. GPU共享内存:pycuda使用教程
  11. springboot如何自定义starter
  12. 【数据库CS751】数据库的建表与插入
  13. ldb文件matlab,MongoDB v4.2.2 安装与配置及常规操作
  14. 习题2.4 编写程序,从键盘输入两个整数分别给变量x,y,如果x大于y,则输出x及x-y的值;否则,输出y及y-x的值
  15. 华为OD机试 - 找朋友(Java JS Python)
  16. java.security.InvalidKeyException:illegal Key Size 报错解决方案
  17. C语言中求两数最大公约数的三种方法
  18. RESTFul与RESTFul案例
  19. vue element-ui 中走马灯自适应图片高度
  20. 糗事百科爬虫用户统计

热门文章

  1. sql in not in_SQL IN – SQL NOT IN
  2. couchdb 安装_如何在Ubuntu上安装CouchDB –分步指南
  3. Spring 4 Security MVC登录注销示例
  4. orm jpa_Spring ORM示例– JPA,Hibernate,事务
  5. 转:C++ string的万能转换
  6. 深入了解什么是服务网格
  7. Java面试锦囊送给你!大厂门槛随便跨!
  8. CentOS7 搭建samba服务
  9. 如何知道PostgreSQL数据库下每个数据库所对应的目录
  10. 系统结构目录与正则表达式