JavaScript正则表达式的分组匹配详解


Posted in Javascript onFebruary 13, 2016

分组

下面的正则表达式可以匹配kidkidkid:

/kidkidkid/

而另一种更优雅的写法是:

/(kid){3}/

这里由圆括号包裹的一个小整体称为分组。

候选

一个分组中,可以有多个候选表达式,用|分隔:

var reg = /I love (him|her|it)/;

reg.test('I love him')  // true 
reg.test('I love her')  // true
reg.test('I love it')  // true
reg.test('I love them') // false

这里的|相当于“或”的意思。

捕获与引用

被正则表达式匹配(捕获)到的字符串会被暂存起来。其中,由分组捕获的串会从1开始编号,于是我们可以引用这些串:

var reg = /(\d{4})-(\d{2})-(\d{2})/
var date = '2010-04-12'
reg.test(date)

RegExp.$1 // 2010
RegExp.$2 // 04
RegExp.$3 // 12

$1引用了第一个被捕获的串,$2是第二个,依次类推。

与replace配合

String.prototype.replace方法的传参中可以直接引用被捕获的串。比如我们想将日期12.21/2012改为2012-12-21:

var reg = /(\d{2}).(\d{2})\/(\d{4})/
var date = '12.21/2012'

date = date.replace(reg, '$3-$1-$2') // date = 2012-12-21

顺道一提,给replace传迭代函数,有时能优雅地解决一些问题。

将违禁词转换为等字数的星号是一个常见功能。比如文本是kid is a doubi,其中kid与doubi是违禁词,那么转换后应该为*** is a *****。我们可以这么写:

var reg = /(kid|doubi)/g
var str = 'kid is a doubi'

str = str.replace(reg, function(word){
  return word.replace(/./g, '*')
})

嵌套分组的捕获

如果碰到类似/((kid) is (a (doubi)))/的嵌套分组,捕获的顺序是什么?来试试:

var reg = /((kid) is (a (doubi)))/
var str = "kid is a doubi"

reg.test( str ) // true

RegExp.$1 // kid is a doubi
RegExp.$2 // kid
RegExp.$3 // a doubi
RegExp.$4 // doubi

规则是以左括号出现的顺序进行捕获。

反向引用

正则表达式里也能进行引用,这称为反向引用:

var reg = /(\w{3}) is \1/

reg.test('kid is kid') // true
reg.test('dik is dik') // true
reg.test('kid is dik') // false
reg.test('dik is kid') // false

\1引用了第一个被分组所捕获的串,换言之,表达式是动态决定的。

注意,如果编号越界了,则会被当成普通的表达式:

var reg = /(\w{3}) is \6/;

reg.test( 'kid is kid' ); // false
reg.test( 'kid is \6' );  // true

分组的类型

分组有四种类型:

捕获型

 - ()
非捕获型

- (?:)
正向前瞻型 - (?=)
反向前瞻型 - (?!)
我们之前说的都是捕获型分组,只有这种分组会暂存匹配到的串。

非捕获型分组

有时候,我们只是想分个组,而没有捕获的需求,则可以使用非捕获型分组,语法为左括号后紧跟?::

var reg = /(?:\d{4})-(\d{2})-(\d{2})/
var date = '2012-12-21'
reg.test(date)

RegExp.$1 // 12
RegExp.$2 // 21

这个例子中,(?:\d{4})分组不会捕获任何串,所以$1为(\d{2})捕获的串。

正向与反向前瞻型分组

就好像你站在原地,向前眺望:

正向前瞻型分组 - 你前方是什么东西吗?
负向前瞻型分组 - 你前方不是什么东西吗?
太拗口了,我喜欢称之为肯定表达式与否定表达式。先举个正向前瞻的例子:

var reg = /kid is a (?=doubi)/

reg.test('kid is a doubi') // true
reg.test('kid is a shabi') // false

kid is a 后面跟着什么?如果是doubi才能匹配成功。

而负向前瞻则刚好相反:

var reg = /kid is a (?!doubi)/

reg.test('kid is a doubi') // false
reg.test('kid is a shabi') // true

如果前瞻型分组也不会捕获值。那么它与非捕获型的区别是什么?看例子:

var reg, str = "kid is a doubi"

reg = /(kid is a (?:doubi))/
reg.test(str)
RegExp.$1 // kid is a doubi

reg = /(kid is a (?=doubi))/
reg.test(str)
RegExp.$1 // kis is a

可见,非捕获型分组匹配到的串,仍会被外层的捕获型分组捕获到,但前瞻型却不会。当你需要参考后面的值,又不想连它一起捕获时,前瞻型分组就派上用场了。

最后,JS不支持后瞻型分组。

Javascript 相关文章推荐
jQuery Animation实现CSS3动画示例介绍
Aug 14 Javascript
node.js中的favicon.ico请求问题处理
Dec 15 Javascript
AngularJS初始化静态模板详解
Jan 14 Javascript
jQuery Easyui实现左右布局
Jan 26 Javascript
简单谈谈json跨域
Mar 13 Javascript
vue监听scroll的坑的解决方法
Sep 07 Javascript
vue全局组件与局部组件使用方法详解
Mar 29 Javascript
jQuery实现侧边栏隐藏与显示的方法详解
Dec 22 jQuery
vue 解决文本框被键盘遮住的问题
Nov 06 Javascript
vue 函数调用加括号与不加括号的区别
Oct 29 Javascript
js异步接口并发数量控制的方法示例
Nov 22 Javascript
原生jQuery实现只显示年份下拉框
Dec 24 jQuery
js HTML5 Ajax实现文件上传进度条功能
Feb 13 #Javascript
js随机生成26个大小写字母
Feb 12 #Javascript
jquery实现具有嵌套功能的选项卡
Feb 12 #Javascript
基于jquery实现动态竖向柱状条特效
Feb 12 #Javascript
原生javascript实现自动更新的时间日期
Feb 12 #Javascript
原生javascript实现图片无缝滚动效果
Feb 12 #Javascript
JavaScript实现点击单元格改变背景色的方法
Feb 12 #Javascript
You might like
PHP设计模式之责任链模式的深入解析
2013/06/13 PHP
php中heredoc与nowdoc介绍
2014/12/25 PHP
Laravel5中contracts详解
2015/03/02 PHP
php简单判断两个字符串是否相等的方法
2015/07/13 PHP
谈谈你对Zend SAPIs(Zend SAPI Internals)的理解
2015/11/10 PHP
php数据库的增删改查 php与javascript之间的交互
2017/08/31 PHP
关于javascript document.createDocumentFragment()
2009/04/04 Javascript
JS获取父节点方法
2009/08/20 Javascript
javascript针对DOM的应用实例(一)
2012/04/15 Javascript
Jquery easyUI 更新行示例
2014/03/06 Javascript
一个简单的jQuery插件ajaxfileupload.js实现ajax上传文件例子
2014/06/26 Javascript
JavaScript中的各种操作符使用总结
2016/05/26 Javascript
Javascript实现通过选择周数显示开始日和结束日的实现代码
2016/05/30 Javascript
JS控制层作圆周运动的方法
2016/06/20 Javascript
hovertree插件实现二级树形菜单(简单实用)
2016/12/28 Javascript
详解Node.js中的Async和Await函数
2018/02/22 Javascript
使用vue根据状态添加列表数据和删除列表数据的实例
2018/09/29 Javascript
javascript中函数的写法实例代码详解
2018/10/28 Javascript
vue生命周期的探索
2019/04/03 Javascript
vue-week-picker实现支持按周切换的日历
2019/06/26 Javascript
layui点击按钮页面会自动刷新的解决方案
2019/10/25 Javascript
在 Vue 中编写 SVG 图标组件的方法
2020/02/24 Javascript
JS实现简易图片自动轮播
2020/10/16 Javascript
详解Python中dict与set的使用
2015/08/10 Python
Flask框架通过Flask_login实现用户登录功能示例
2018/07/17 Python
python三方库之requests的快速上手
2019/03/04 Python
Python爬虫学习之翻译小程序
2019/07/30 Python
如何用OpenCV -python3实现视频物体追踪
2019/12/04 Python
python 解决tqdm模块不能单行显示的问题
2020/02/19 Python
Python-jenkins 获取job构建信息方式
2020/05/12 Python
通过Python实现一个简单的html页面
2020/05/16 Python
中国宠物用品商城:E宠商城
2016/08/27 全球购物
方太官方网上商城:销售方太抽油烟机、燃气灶、消毒柜等
2017/01/17 全球购物
学校办公室主任职责
2013/12/27 职场文书
工商局局长个人对照检查材料思想汇报
2014/09/23 职场文书
2019安全宣传标语大全
2019/08/14 职场文书