文档章节

正则表达式中的零宽先行断言

马子
 马子
发布于 2017/08/18 16:20
字数 1003
阅读 26
收藏 0

最近学习了正则表达式,对于零宽先行断言这部分遇到了一些问题,简单记一下吧

零宽断言分为零宽先行断言和零宽后发断言(其中JavaScript只支持零宽先行断言,不支持零宽后发断言)

1、零宽先行断言(零宽度正预测先行断言和零宽度负预测先行断言)

 (1)零宽度正预测先行断言(?= 子表达式)
        个人理解:自身出现的位置的后面能匹配子表达式
        例如

var str="abcDEFG888";
var reg=/abc(?=[A-Z])/;
console.log(str.match(reg));


        在以上代码中,正则表达式的语义是:匹配后面跟随任意一个大写字母的字符串"abc"。最终匹配结果是"abc",因为零宽断言"(?=[A-Z])"并不匹配任何字符(从“零宽”二字也可以看得出来),只是用来规定当前位置的后面必须是一个大写字母。

  (2)零宽度负预测先行断言(?!子表达式)
        个人理解:自身出现的位置的后面不能匹配子表达式
        例如   

var str="abcDEFG666";
var reg=/abc(?![A-Z])/;
console.log(str.match(reg));


        以上代码中,正则表达式的语义是:匹配后面不跟随任意一个大写字母的字符串"abc"。正则表达式没能匹配任何字符,因为在字符串中,abc的后面跟随有大写字母。

        注意:

        在学习正则表达式的过程中,遇到了一个问题,就是写了一个匹配3位数字之后非数字的正则表达式

        /\d{3}(?!\d)/

var pattren = /\d{3}(?!\d)/;
var str = '1111';
console.log(str.match(pattren));

        当我的检测字符串为'1111'的时候,应当匹配失败,因为111的后面跟的是1这个数字,而零宽断言要求非数字。但是当在控制台测试的时候,却匹配成功了,出现了以下的情况
       

        结果匹配成功了,让我不明所以,于是网上多方查找,发现了如下一段话:

var reg = new Regex(@"a(?=b)c");
var str = "abc";
Console.WriteLine(reg.IsMatch(str));//返回false

      为什么会返回false?

     其实msdn官方定义已经说了,只是它说得很官方而已。这里需要我们注意一个关键点:此位置。没错,是位置而不是字符。那么结合官方定义和第一个例子来理解第二个例子:

     因为a后面是b,则此时返回了匹配内容a(由第一个例子知道,只返回a不返回exp匹配的内容),此时a(?=b)c中的a(?=b)部分已经解决了,接下来要解决c的匹配问题了,此时匹配c要从字符串abc哪里开始呢,结合官方定义,就知道是从子表达的位置向右开始的,那么就是从b的位置开始,但b又不匹配a(?=b)c剩余部分的c,所以abc就不匹配a(?=b)c了。

     那么如果要上面的进行匹配,正则应该如何写呢?

     答案是:a(?=b)bc

     当然,有人会说直接abc就匹配上了,还要这么折腾吗?当然不用这么折腾,只是为了说明零宽度正预测先行断言到底是怎么一回事?关于其它的零宽断言也是同一原理!

       从这里可以看出,零宽断言的核心始终是“零宽”,判断的是“位置”而不是“字符”,再结合前文,就能得出答案了

var pattren = /\d{3}(?!\d)/;
var str = '1111';
console.log(str.match(pattren));

        以上代码的正则表达式能匹配的原因是,空字符串也满足子表达式的条件。即3个数字后面,什么都不跟也可以。所以最终匹配结果为:从index为1的索引即第二个1开始匹配,3个数字+一个非数字(空字符串),匹配成功,所以返回["111", index: 1, input: "1111"]。
   

© 著作权归作者所有

马子
粉丝 1
博文 1
码字总数 1003
作品 0
沙坪坝
程序员
私信 提问
【正则表达式系列】零宽断言

前言 本文属于 正则表达式系列文章之一,更多请前往 正则表达式系列 正则表达式中,有一个绕不过去的坎,那就是 是一种零宽度的匹配,它匹配的内容不会保存到匹配结果中,也不会占用宽度,最...

撒网要见鱼
2017/07/26
0
0
正则表达式的先行断言(lookahead)和后行断言(lookbehind)

正则表达式的先行断言和后行断言一共有4种形式: (?=pattern) 零宽正向先行断言(zero-width positive lookahead assertion) (?!pattern) 零宽负向先行断言(zero-width negative lookahead as...

吟啸_徐行
2014/07/27
560
0
锱铢必较:程序员生存指南——正则表达式中使用断言

想让一个名词听起来特别高大上,最简单的方法就是加很多修饰语。比如多源异构群智协同负反馈深度神经网络(当然了,这是我瞎编的)。在正则表达式中,有一种东西叫断言,它的修饰语也很多: ...

大神带我来搬砖
2018/06/05
0
0
Java魔法堂:深入正则表达式API

目录                               一、前言 二、正则表达式的使用诉求 三、java.util.regex包 四、java.lang.String实例 五、最短路径实现诉求 六、Java支...

fsjohnhuang
2014/11/16
166
0
老男孩带你了解perl正则表达式中的零宽断言

老男孩IT教育小编为大家整理了perl正则表达式中的零宽断言的方法,希望能帮到大家 1.1 前言 本文只介绍perl语言正则表达式的零宽断言功能。 零宽断言实质:匹配文本里面的位置。 零宽断言叫z...

运维自动化
2017/05/31
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Qt程序打包发布方法(使用官方提供的windeployqt工具)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/toTheUnknown/article/details/81748179 如果使用到了Qt ...

shzwork
29分钟前
4
0
MainThreadSupport

MainThreadSupport EventBus 3.0 中的代码片段. org.greenrobot.eventbus.MainThreadSupport 定义一个接口,并给出默认实现类. 调用者可以在EventBus的构建者中替换该实现. public interface ...

马湖村第九后羿
49分钟前
3
0
指定要使用的形状来代替文字的显示

控制手机键盘弹出的功能只能在ios上实现,安卓是实现不了的,所以安卓只能使用type类型来控制键盘类型,例如你要弹出数字键盘就使用type="number",如果要弹出电话键盘就使用type="tel",但这...

前端老手
今天
6
0
总结:Raft协议

一、Raft协议是什么? 分布式一致性算法。即解决分布式系统中各个副本数据一致性问题。 二、Raft的日志广播过程 发送日志到所有Followers(Raft中将非Leader节点称为Follower)。 Followers收...

浮躁的码农
今天
7
0
Flask-admin Model View字段介绍

Model View字段介绍 can_create = True 是否可以创建can_edit = True 是否可以编辑can_delete = True 是否可以删除list_template = 'admin/model/list.html' 修改显......

dillonxiao
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部