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显示隐藏层比较不错的方法分析
Sep 30 Javascript
Javascript笔记一 js以及json基础使用说明
May 22 Javascript
js jquery验证银行卡号信息正则学习
Jan 21 Javascript
详解JavaScript ES6中的模板字符串
Jul 28 Javascript
全系IE支持Bootstrap的解决方法
Oct 19 Javascript
Javascript获取数组中的最大值和最小值的方法汇总
Jan 01 Javascript
javascript事件绑定学习要点
Mar 09 Javascript
Bootstrap3制作图片轮播效果
May 12 Javascript
聊一聊jQuery插件uploadify使用方法
Aug 24 Javascript
Vue下的国际化处理方法
Dec 18 Javascript
vue element-ui中table合计指定列求和实例
Nov 02 Javascript
一篇文章学会Vue中间件管道
Jun 20 Vue.js
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
收集的DedeCMS一些使用经验
2007/03/17 PHP
解析PHP对现有搜索引擎的调用
2013/06/25 PHP
php多任务程序实例解析
2014/07/19 PHP
JScript内置对象Array中元素的删除方法
2007/03/08 Javascript
Javascript 获取字符串字节数的多种方法
2009/06/02 Javascript
JavaScript基础知识之数据类型
2012/08/06 Javascript
jQuery动态背景图片效果实现方法
2015/07/03 Javascript
JavaScript实现表格快速变色效果代码
2015/08/19 Javascript
详解JavaScript中的Unescape()和String() 函数
2015/11/09 Javascript
浅析Javascript中bind()方法的使用与实现
2016/04/29 Javascript
基于js实现二级下拉联动
2016/12/17 Javascript
angularjs实现的前端分页控件示例
2017/02/10 Javascript
详解win7 cmd执行vue不是内部命令的解决方法
2017/07/27 Javascript
vue中实现滚动加载更多的示例
2017/11/08 Javascript
Vue之Vue.set动态新增对象属性方法
2018/02/23 Javascript
Angular6中使用Swiper的方法示例
2018/07/09 Javascript
JS实现求5的阶乘示例
2019/01/21 Javascript
详解JSON和JSONP劫持以及解决方法
2019/03/08 Javascript
javascript function(函数类型)使用与注意事项小结
2019/06/10 Javascript
通过js给网页加上水印背景实例
2019/06/17 Javascript
typescript nodejs 依赖注入实现方法代码详解
2019/07/21 NodeJs
[01:36:17]DOTA2-DPC中国联赛 正赛 Ehome vs iG BO3 第一场 1月31日
2021/03/11 DOTA
python 字符串split的用法分享
2013/03/23 Python
如何解决django-celery启动后迅速关闭
2019/10/16 Python
python GUI库图形界面开发之PyQt5下拉列表框控件QComboBox详细使用方法与实例
2020/02/27 Python
通过实例解析Python return运行原理
2020/03/04 Python
python自动生成证件号的方法示例
2021/01/14 Python
python如何修改文件时间属性
2021/02/05 Python
Fairyseason:为个人和批发商提供女装和配件
2017/03/01 全球购物
TheFork葡萄牙:欧洲领先的在线餐厅预订平台
2019/05/27 全球购物
如何获得EntityManager
2014/02/09 面试题
幼儿园中班教学反思
2014/02/10 职场文书
气象学专业个人求职信
2014/03/15 职场文书
酒店财务总监岗位职责
2015/04/03 职场文书
Python OpenCV快速入门教程
2021/04/17 Python
Unicode中的CJK(中日韩统一表意文字)字符小结
2021/12/06 HTML / CSS