javascript正则断言的理解

之前大三学习《编译原理》的时候老师讲了点叫断言的东西,但是这门课压根就没听懂过,所以一直找不到有价值的东西,好吧原谅我懒惰无知,理论不适合我,我只适合搬砖。许久之后一些关于正则的黑科技才发现正则里也有较断言的东东,好吧得了解了解这是什么。

那么正则里的断言是什么?

引用一段来自百科的说明

用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们像b,^,$那样用于指定一个位置,这个位置应该满足一定的条件(即断言),因此它们也被称为零宽断言。(来自百度百科)

断言在一些教材里也称作环视

断言写法

  • 前瞻断言

    • (?=exp) 顺序肯定环视,表示所在位置右侧能够匹配exp

    • (?!exp) 顺序否定环视,表示所在位置右侧不能匹配exp

  • 后瞻断言

    • (?<=exp) 逆序肯定环视,表示所在位置左侧能够匹配exp

    • (?<!exp) 逆序否定环视,表示所在位置左侧不能匹配exp

解析:
前瞻断言(从当前位置向前测试)和后瞻断言(从当前位置向后测试)。

具体的例子看使用方法吧。

注:

  • 括号是必须的,写法:(?!=...)

  • 有些语言并不完全支持,比如:javascript的正则并不支持后瞻断言表达式,使用了会报错的。

  • 其中exp是一个正则表达式可以是子模式,如:(?=((exp))

  • 环视也称断言;断言是不占用字符串的((?=exp)所以不能引用,exp是占用字符串的)

使用方法

  • (?=exp) 顺序肯定环视,表示所在位置右侧能够匹配exp

来个javascript的例子,匹配.gif的文件名

var s="img.jpg,abc.gif,123.jpeg";
s.match(/\w*(?=\.gif)/);

结果:["abc"]

/\w*(?=\.gif)/中的\w*表示可以有零个或多个字符,匹配到的是abc,那么(?=.gif)这个匹配到什么?其实他匹配到的只是一个位置,这就是断言的初衷,匹配到的是介于abc.gif的位置。
好吧不信来验证下:
去掉正则表达式的\w*,在匹配到的内容替换成#

var s="img.jpg,abc.gif,123.jpeg";
s.replace(/(?=\.gif)/,"#");

结果:"img.jpg,abc#.gif,123.jpeg"

回到定义:(?=exp)顺序肯定环视,表示所在位置右侧能够匹配exp;那么/\w*(?=\.gif)/的意思就是以.gif作为右边的位置才匹配成功,那就会匹配到abc.gif这里就成功了,之前说过断言匹配不占用字符宽度(即不结果不会包含断言部分),所以匹配到的字符串就是\w*即'abc'。

  • (?!exp) 顺序否定环视,表示所在位置右侧不能匹配exp

例子:匹配非.gif的文件名

var s="img.jpg,abc.gif,123.jpeg";
s.match(/(\w*)(?:\.)(?!gif)\w*/g);

结果:["img.jpg", "123.jpeg"]

/(\w*)(?:\.)(?!gif)\w*/g这个正则表示(\w*)(?:\.)的右边不是gif匹配成功。

对于后瞻断言的例子这里不举例子,如果哪位有空填下吧。

使用例子

来看一个来自网络的问答例子:把一串数10000000000字以,分隔成10,000,000,000

这个例子0有点多看着耀眼,先从简单的开始;好吧我们换一串字符串比如:12345678转换成12,345,678

正则怎么实现呢?
看代码:

var s="12345678";
s.replace(/(?=(\d{3})+(?!\d))/g,",");

是的就这样就可以了。
好吧,来分析下原理:

/(?=(\d{3})+(?!\d))/g,其中(\d{3})+表示前面的三个数字串至少出现一组,而后接(?!\d)则表示的是数字的右边不是数字,
那么就是结尾,那/(?=(\d{3})+(?!\d))/匹配到的位置就是12345678之间的位置,加了g表全局匹配,
所以继续匹配到满足条件的345678之间的位置,在这些加,就有了12,345,678了。

如果想看这个例子的过程可以改写下代码:


var s="12345678";
s.replace(/(?=((\d{3})+)(?!\d))/g,function(){console.log(arguments);return ","});

结果:
循环1: ["", "345678", "678", 2, "12345678"]
循环2: ["", "678", "678", 5, "12345678"]
返回值:"12,345,678"

好吧,原理不再细说,自己复制代码到浏览器控制台执行看效果。

那么这个10000000000转成10,000,000,000就很简单了。

但是如果数字串的位数是3的倍数会出现在数字串前面也有一个,号,好吧再正则去掉result.replace(",","")

后语

上面举的一些例子可能不足以说明问题,如果你是精通正则的高手望勿喷,当然多多指教那就更好了。


WEB 攻城方略
专注web技术分享
1 篇内容引用

Front End & Back End(Node.js) Developer

2.2k 声望
57 粉丝
0 条评论
推荐阅读
vue-dotmd-loader 用于 markdown 转 vue 组件的 webpack loader
vue-dotmd-loader Docs | Github 用于把 markdown 文件转成 Vue 组件的 webpack laoder 工具包。 {代码...} 特性: [x] 支持导入 Vue 文件组件渲染成 Vue 组件实例 [x] 代码块支持高亮指定行 [x] md里支持编写 Vu...

mengdu2阅读 3.7k

从零搭建 Node.js 企业级 Web 服务器(零):静态服务
过去 5 年,我前后在菜鸟网络和蚂蚁金服做开发工作,一方面支撑业务团队开发各类业务系统,另一方面在自己的技术团队做基础技术建设。期间借着 Node.js 的锋芒做了不少 Web 系统,有的至今生气蓬勃、有的早已夭折...

乌柏木141阅读 11.9k评论 10

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木60阅读 5.9k评论 16

再也不学AJAX了!(二)使用AJAX ① XMLHttpRequest
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第二篇,最近更新于 2023 年 1...

libinfs39阅读 6.1k评论 12

封面图
从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
分层规范从本章起,正式进入企业级 Web 服务器核心内容。通常,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,如下图:从上至下,抽象层次逐渐加深。从下至上,业务细节逐渐清晰。视图...

乌柏木39阅读 7.1k评论 6

【关于Javascript】--- 正则表达式篇
基础知识一、元字符 {代码...} 二、量词 {代码...} 三、集合 字符类 {代码...} 四、分支 {代码...} 五、边界 开始结束 {代码...} 六、修饰符 {代码...} 七、贪婪模式和非贪婪模式js默认贪婪模式即最大可能的匹配...

Jerry35阅读 2.9k

从零搭建 Node.js 企业级 Web 服务器(二):校验
校验就是对输入条件的约束,避免无效的输入引起异常。Web 系统的用户输入主要为编辑与提交各类表单,一方面校验要做在编辑表单字段与提交的时候,另一方面接收表单的接口也要做足校验行为,通过前后端共同控制输...

乌柏木32阅读 6k评论 9

Front End & Back End(Node.js) Developer

2.2k 声望
57 粉丝
宣传栏