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的AutoComplete插件
May 04 Javascript
js 3种归并操作的实例代码
Oct 30 Javascript
浅谈JavaScript字符集
May 22 Javascript
js计算德州扑克牌面值的方法
Mar 04 Javascript
javascript实现表单提交后,提交按钮不可用的方法
Apr 18 Javascript
wangEditor编辑器失去焦点后仍然可以在原位置插入图片分析
May 06 Javascript
javascript框架设计之种子模块
Jun 23 Javascript
jQuery解析Json实例详解
Nov 24 Javascript
JavaScrpt中如何使用 cookie 设置查看与删除功能
Jul 09 Javascript
详解使用VUE搭建后台管理系统(vue-cli更新至3.0)
Aug 22 Javascript
vue基于viewer实现的图片查看器功能
Apr 12 Javascript
基于JQuery和DWR实现异步数据传递
Oct 16 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中关于普通表单多文件上传的处理方法
2011/03/25 PHP
PHP显示今天、今月、上月、今年的起点/终点时间戳的代码
2011/05/25 PHP
PHP FOR MYSQL 代码生成助手(根据Mysql里的字段自动生成类文件的)
2011/07/23 PHP
php过滤html标记属性类用法实例
2014/09/23 PHP
php中json_encode不兼容JSON_UNESCAPED_UNICODE的解决方案
2016/05/31 PHP
PHP实现笛卡尔积算法的实例讲解
2019/12/22 PHP
类似CSDN图片切换效果脚本
2009/09/17 Javascript
functional继承模式 摘自javascript:the good parts
2011/06/20 Javascript
js预载入和JavaScript Image()对象使用介绍
2011/08/28 Javascript
node.js入门教程迷你书、node.js入门web应用开发完全示例
2014/04/06 Javascript
jquery如何把数组变为字符串传到服务端并处理
2014/04/30 Javascript
IE中图片的onload事件无效问题和解决方法
2014/06/06 Javascript
node.js中的fs.fsync方法使用说明
2014/12/15 Javascript
jQuery form插件之formDdata参数校验表单及验证后提交
2016/01/23 Javascript
jquery uploadify如何取消已上传成功文件
2017/02/08 Javascript
BootStrap中jQuery插件Carousel实现轮播广告效果
2017/03/27 jQuery
jQuery实现的点击图片居中放大缩小功能示例
2019/01/16 jQuery
Vue 无限滚动加载指令实现方法
2019/05/28 Javascript
解决vue的过渡动画无法正常实现问题
2019/10/31 Javascript
Vuejs中的watch实例详解(监听者)
2020/01/05 Javascript
微信小程序单选框自定义赋值
2020/05/26 Javascript
Python实现在线程里运行scrapy的方法
2015/04/07 Python
Python实现查询某个目录下修改时间最新的文件示例
2018/08/29 Python
如何利用python给图片添加半透明水印
2019/09/06 Python
TensorFlow tensor的拼接实例
2020/01/19 Python
python中threading和queue库实现多线程编程
2021/02/06 Python
FORZIERI澳大利亚站:全球顶级奢华配饰精品店
2016/12/31 全球购物
贸易经济专业自荐书
2014/06/29 职场文书
助残日活动总结
2014/08/27 职场文书
2014各大专业毕业生自我评价
2014/09/17 职场文书
学期个人工作总结
2015/02/13 职场文书
幼儿园六一主持词开场白
2015/05/28 职场文书
不知如何爱孩子,这些方法教会您
2019/08/06 职场文书
Python selenium的这三种等待方式一定要会!
2021/06/10 Python
TV动画《八十龟酱观察日记》第四季宣传PV公布
2022/04/06 日漫
关于Redis的主从复制及哨兵问题
2022/06/16 Redis