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编程起步(第六课)
Jan 10 Javascript
js 纯数字不重复排列的另类方法
Jul 17 Javascript
JS localStorage实现本地缓存的方法
Jun 22 Javascript
div+css+js实现无缝滚动类似marquee无缝滚动兼容firefox
Aug 29 Javascript
jQuery实现单击按钮遮罩弹出对话框(仿天猫的删除对话框)
Apr 10 Javascript
javascript中replace( )方法的使用
Apr 24 Javascript
javascript实现添加附件功能的方法
Nov 18 Javascript
浅析JavaScript声明变量
Dec 21 Javascript
bootstrap3 兼容IE8浏览器!
May 02 Javascript
JavaScript中递归实现的方法及其区别
Sep 12 Javascript
Vue使用NProgress进度条的方法
Sep 21 Javascript
Typescript类型系统FLOW静态检查基本规范
May 25 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
通过对服务器端特性的配置加强php的安全
2006/10/09 PHP
php array_walk() 数组函数
2011/07/12 PHP
php获取用户IPv4或IPv6地址的代码
2012/11/15 PHP
linux使用crontab实现PHP执行计划定时任务
2014/05/10 PHP
phpMyAdmin安装并配置允许空密码登录
2015/07/04 PHP
完美解决php 导出excle的.csv格式的数据时乱码问题
2017/02/18 PHP
PHP实现字符串大小写转函数的功能实例
2019/02/06 PHP
php中的依赖注入实例详解
2019/08/14 PHP
JavaScript Title、alt提示(Tips)实现源码解读
2010/12/12 Javascript
最常用的12种设计模式小结
2011/08/09 Javascript
JavaScript 5 新增 Array 方法实现介绍
2012/02/06 Javascript
js日期时间补零的小例子
2013/03/05 Javascript
JS动态获取当前时间,并写到特定的区域
2013/05/03 Javascript
js实现jquery的offset()方法实例
2015/01/10 Javascript
JavaScript实现选择框按比例拖拉缩放的方法
2015/08/04 Javascript
AngularJS框架的ng-app指令与自动加载实现方法分析
2017/01/04 Javascript
vue router仿天猫底部导航栏功能
2017/10/18 Javascript
详解vue中axios的封装
2018/07/18 Javascript
jquery判断滚动条距离顶部的距离方法
2018/09/05 jQuery
angular 表单验证器验证的同时限制输入的实现
2019/04/11 Javascript
在Python中测试访问同一数据的竞争条件的方法
2015/04/23 Python
python使用range函数计算一组数和的方法
2015/05/07 Python
Python操作redis实例小结【String、Hash、List、Set等】
2019/05/16 Python
让Python脚本暂停执行的几种方法(小结)
2019/07/11 Python
Columbia美国官网:美国著名的户外服装品牌
2016/11/24 全球购物
Whittard官方海外旗舰店:英国百年茶叶品牌
2018/02/22 全球购物
怎样声明子类
2013/07/02 面试题
Linux文件系统类型
2012/02/15 面试题
大学生毕业自荐信
2013/10/10 职场文书
入党申请人的自我鉴定
2013/12/01 职场文书
战友聚会邀请函
2014/01/18 职场文书
审计主管岗位职责
2014/01/31 职场文书
2014学校领导四风问题对照检查材料思想汇报
2014/09/22 职场文书
2014年科研工作总结
2014/12/03 职场文书
高三语文复习计划
2015/01/19 职场文书
羊脂球读书笔记
2015/06/30 职场文书