javascript 正则表达式分组、断言详解


Posted in Javascript onApril 20, 2017

 javascript 正则表达式分组、断言详解

  提示:阅读本文需要有一定的正则表达式基础。

       正则表达式中的断言,作为高级应用出现,倒不是因为它有多难,而是概念比较抽象,不容易理解而已,今天就让小菜通俗的讲解一下。

       如果不用断言,以往用过的那些表达式,仅仅能获取到有规律的字符串,而不能获取无规律的字符串。

       举个例子,比如html源码中有<title>xxx</title>标签,用以前的知识,我们只能确定源码中的<title>和</title>是固定不变的。因此,如果想获取页面标题(xxx),充其量只能写一个类似于这样的表达式:<title>.*</title>,而这样写匹配出来的是完整的<title>xxx</title>标签,并不是单纯的页面标题xxx。

       想解决以上问题,就要用到断言知识。

       在讲断言之前,读者应该先了解分组,这有助于理解断言。

       分组在正则中用()表示,根据小菜理解,分组的作用有两个:

       n  将某些规律看成是一组,然后进行组级别的重复,可以得到意想不到的效果。

       n  分组之后,可以通过后向引用简化表达式。

        先来看第一个作用,对于IP地址的匹配,简单的可以写为如下形式:

       \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}

       但仔细观察,我们可以发现一定的规律,可以把.\d{1,3}看成一个整体,也就是把他们看成一组,再把这个组重复3次即可。表达式如下:

       \d{1,3}(.\d{1,3}){3}

       这样一看,就比较简洁了。

再来看第二个作用,就拿匹配<title>xxx</title>标签来说,简单的正则可以这样写:

       <title>.*</title>

       可以看出,上边表达式中有两个title,完全一样,其实可以通过分组简写。表达式如下:

       <(title)>.*</\1>

       这个例子实际上就是反向引用的实际应用。对于分组而言,整个表达式永远算作第0组,在本例中,第0组是<(title)>.*</\1>,然后从左到右,依次为分组编号,因此,(title)是第1组。

       用\1这种语法,可以引用某组的文本内容,\1当然就是引用第1组的文本内容了,这样一来,就可以简化正则表达式,只写一次title,把它放在组里,然后在后边引用即可。

       以此为启发,我们可不可以简化刚刚的IP地址正则表达式呢?原来的表达式为\d{1,3}(.\d{1,3}){3},里边的\d{1,3}重复了两次,如果利用后向引用简化,表达式如下:

       (\d{1,3})(.\1){3}

       简单的解释下,把\d{1,3}放在一组里,表示为(\d{1,3}),它是第1组,(.\1)是第2组,在第2组里通过\1语法,后向引用了第1组的文本内容。

       经过实际测试,会发现这样写是错误的,为什么呢?

       小菜一直在强调,后向引用,引用的仅仅是文本内容,而不是正则表达式!

       也就是说,组中的内容一旦匹配成功,后向引用,引用的就是匹配成功后的内容,引用的是结果,而不是表达式。

       因此,(\d{1,3})(.\1){3}这个表达式实际上匹配的是四个数都相同的IP地址,比如:123.123.123.123。

       至此,读者已经掌握了传说中的后向引用,就这么简单。

       接下来说说什么是断言。

       所谓断言,就是指明某个字符串前边或者后边,将会出现满足某种规律的字符串。

       就拿文章开篇的例子来说,我们想要的是xxx,它没有规律,但是它前边肯定会有<title>,后边肯定会有</title>,这就足够了。

       想指定xxx前肯定会出现<title>,就用正后发断言,表达式:(?<=<title>).*

       向指定xxx后边肯定会出现</title>,就用正先行断言,表达式:.*(?=</title>)

       两个加在一起,就是(?<=<title>).*(?=</title>)

       这样就能匹配到xxx。

     

       相信读者看到这,已经蒙了,不用急,待小菜慢慢讲来。

     

       其实掌握了规律,就很简单了,无论是先行还是后发,都是相对于xxx而言的,也就是相对于目标字符串而言。

       假如目标字符串后边有条件,可以理解为目标字符串在前,就用先行断言,放在目标字符串之后。

       假如目标字符串前边有条件,可以理解为目标字符串在后,就用后发断言,放在目标字符串之前。

       假如指定满足某个条件,就是正。

       假如指定不满足某个条件,就是负。

       断言只是条件,帮你找到真正需要的字符串,本身并不会匹配!

(?=X ) 零宽度正先行断言。仅当子表达式 X 在 此位置的右侧匹配时才继续匹配。例如,/w+(?=/d) 与后跟数字的单词匹配,而不与该数字匹配。此构造不会回溯。
(?!X) 零宽度负先行断言。仅当子表达式 X 不在 此位置的右侧匹配时才继续匹配。例如,例如,/w+(?!/d) 与后不跟数字的单词匹配,而不与该数字匹配 。
(? 零宽度正后发断言。仅当子表达式 X 在 此位置的左侧匹配时才继续匹配。例如,(?
(? 零宽度负后发断言。仅当子表达式 X 不在此位置的左侧匹配时才继续匹配。例如,(?

       从断言的表达形式可以看出,它用的就是分组符号,只不过开头都加了一个问号,这个问号就是在说这是一个非捕获组,这个组没有编号,不能用来后向引用,只能当做断言。

       教程到此结束,希望大家阅读愉快!

Javascript 相关文章推荐
javascript 常用代码技巧大收集
Feb 25 Javascript
document.getElementById方法在Firefox与IE中的区别
May 18 Javascript
js实现鼠标拖动图片并兼容IE/FF火狐/谷歌等主流浏览器
Jun 06 Javascript
JavaScript中把数字转换为字符串的程序代码
Jun 19 Javascript
js获取url中&quot;?&quot;后面的字串方法
May 15 Javascript
jQuery实现鼠标可拖动调整表格列宽度
May 26 Javascript
JavaScript代码因逗号不规范导致IE不兼容的问题
Feb 25 Javascript
DIV+CSS+jQ实现省市联动可扩展
Jun 22 Javascript
JS轮播图中缓动函数的封装
Nov 25 Javascript
浅谈Vue.js
Mar 02 Javascript
详解angular分页插件tm.pagination二次触发问题解决方案
Jul 20 Javascript
在vue中使用inheritAttrs实现组件的扩展性介绍
Dec 07 Vue.js
jQuery插件FusionCharts绘制的3D双柱状图效果示例【附demo源码】
Apr 20 #jQuery
JS利用cookies设置每隔24小时弹出框
Apr 20 #Javascript
一篇看懂vuejs的状态管理神器 vuex状态管理模式
Apr 20 #Javascript
addEventListener()与removeEventListener()解析
Apr 20 #Javascript
详解用vue-cli来搭建vue项目和webpack
Apr 20 #Javascript
js禁止浏览器的回退事件
Apr 20 #Javascript
vue-cli入门之项目结构分析
Apr 20 #Javascript
You might like
9个比较实用的php代码片段
2016/03/15 PHP
基于jquery的DIV随滚动条滚动而滚动的代码
2012/07/20 Javascript
jQuery图片轮播的具体实现
2013/09/11 Javascript
js 实现浏览历史记录示例
2014/04/20 Javascript
JavaScript极简入门教程(一):基础篇
2014/10/25 Javascript
jQuery插件bgStretcher.js实现全屏背景特效
2015/06/05 Javascript
Javascript中的getUTCHours()方法使用详解
2015/06/10 Javascript
js与applet相互调用的方法
2016/06/22 Javascript
jquery遍历标签中自定义的属性方法
2016/09/17 Javascript
Bootstrap模态框水平垂直居中与增加拖拽功能
2016/11/09 Javascript
JS实现加载时锁定HTML页面元素的方法
2017/06/24 Javascript
Vee-Validate的使用方法详解
2017/09/22 Javascript
js断点调试经验分享
2017/12/08 Javascript
vue父组件点击触发子组件事件的实例讲解
2018/02/08 Javascript
简单说说如何使用vue-router插件的方法
2019/04/08 Javascript
微信公众号获取用户地理位置并列出附近的门店的示例代码
2019/07/25 Javascript
vue-cli3.0实现一个多页面应用的历奇经历记录总结
2020/03/16 Javascript
全面了解python字符串和字典
2016/07/07 Python
python 3.6 +pyMysql 操作mysql数据库(实例讲解)
2017/12/20 Python
使用django和vue进行数据交互的方法步骤
2019/11/11 Python
Python socket处理client连接过程解析
2020/03/18 Python
python实现按键精灵找色点击功能教程,使用pywin32和Pillow库
2020/06/04 Python
Python selenium爬取微信公众号文章代码详解
2020/08/12 Python
通过Django Admin+HttpRunner1.5.6实现简易接口测试平台
2020/11/11 Python
汇科协同Java笔试题
2012/03/31 面试题
最新党员的自我评价分享
2013/11/04 职场文书
体育教育毕业生自荐信
2013/11/21 职场文书
运动会领导邀请函
2014/02/05 职场文书
增员口号大全
2014/06/18 职场文书
个人授权委托书范文
2014/09/21 职场文书
神龙架导游词
2015/02/11 职场文书
青岛海底世界导游词
2015/02/11 职场文书
在职证明范本
2015/06/15 职场文书
法人身份证明书
2015/06/18 职场文书
《跨越海峡的生命桥》教学反思
2016/02/18 职场文书
python+opencv实现目标跟踪过程
2022/06/21 Python