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 相关文章推荐
用javascript实现的仿Flash广告图片轮换效果
Apr 24 Javascript
JavaScript初学者应注意的七个细节小结
Jan 30 Javascript
jquery实现动态菜单的实例代码
Nov 28 Javascript
javascript正则表达式参数/g与/i及/gi的使用指南
Aug 27 Javascript
jquery学习总结(超级详细)
Sep 04 Javascript
JavaScript中Number.NEGATIVE_INFINITY值的使用详解
Jun 05 Javascript
jQuery判断浏览器并动态调整select宽度的方法
Mar 02 Javascript
详解jQuery中的事件
Dec 14 Javascript
Web前端框架bootstrap实战【第一次接触使用】
Dec 28 Javascript
监听angularJs列表数据是否渲染完毕的方法示例
Nov 07 Javascript
详解VUE调用本地json的使用方法
May 15 Javascript
JS实现瀑布流效果
Mar 07 Javascript
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
建立动态的WML站点(二)
2006/10/09 PHP
PHP常用函数小技巧
2008/09/11 PHP
PHP zlib扩展实现页面GZIP压缩输出
2010/06/17 PHP
PHP中foreach循环中使用引用要注意的地方
2011/01/02 PHP
php中session与cookie的比较
2015/01/27 PHP
php实现word转html的方法
2016/01/22 PHP
tp5框架无刷新分页实现方法分析
2019/09/26 PHP
一个js封装的不错的选项卡效果代码
2008/02/15 Javascript
js生成动态表格并为每个单元格添加单击事件的方法
2014/04/14 Javascript
AngularJS内置指令
2015/02/04 Javascript
JavaScript如何禁止Backspace键
2015/12/02 Javascript
关于js函数解释(包括内嵌,对象等)
2016/11/20 Javascript
JavaScript解析JSON格式数据的方法示例
2017/01/24 Javascript
详解ElementUI之表单验证、数据绑定、路由跳转
2017/06/21 Javascript
基于vue-cli vue-router搭建底部导航栏移动前端项目
2018/02/28 Javascript
将RGB值转换为灰度值的简单算法
2019/10/09 Javascript
[36:29]2018DOTA2亚洲邀请赛 4.1 小组赛 A组加赛 LGD vs TNC
2018/04/02 DOTA
[42:56]VGJ.S vs Serenity 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
深入解析Python中的urllib2模块
2015/11/13 Python
Python实现按当前日期(年、月、日)创建多级目录的方法
2018/04/26 Python
python实现超市管理系统(后台管理)
2019/10/25 Python
python3正则模块re的使用方法详解
2020/02/11 Python
python selenium操作cookie的实现
2020/03/18 Python
python中前缀运算符 *和 **的用法示例详解
2020/05/28 Python
CSS3圆角边框和边界图片效果实例
2016/07/01 HTML / CSS
Html5新标签datalist实现输入框与后台数据库数据的动态匹配
2017/05/18 HTML / CSS
SIMON MILLER官网:洛杉矶的生活方式品牌
2020/10/19 全球购物
烹饪自我鉴定
2014/03/01 职场文书
社区道德讲堂实施方案
2014/03/21 职场文书
找工作求职信
2014/07/07 职场文书
运动会演讲稿50字
2014/08/25 职场文书
小学班级特色活动方案
2014/08/31 职场文书
2014教育局对照检查材料思想汇报
2014/09/23 职场文书
logback如何自定义日志存储
2021/08/30 Java/Android
一文带你探究MySQL中的NULL
2021/11/11 MySQL
如何Python使用re模块实现okenizer
2022/04/30 Python