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 相关文章推荐
限制复选框的最大可选数
Jul 01 Javascript
javascript 解析url的search方法
Feb 09 Javascript
javascript中如何处理引号编码"
Aug 15 Javascript
js的alert弹出框出现乱码解决方案
Sep 02 Javascript
在JavaScript中处理时间之setMinutes()方法的使用
Jun 11 Javascript
js中遍历Map对象的方法
Jul 27 Javascript
javascript 正则表达式去空行方法
Jan 24 Javascript
微信小程序学习之数据处理详解
Jul 05 Javascript
React Native中NavigatorIOS组件的简单使用详解
Jan 27 Javascript
vue项目中vue-i18n和element-ui国际化开发实现过程
Apr 25 Javascript
Vue实现点击时间获取时间段查询功能
Aug 21 Javascript
vue.js打包之后可能会遇到的坑!
Jun 03 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字符转义相关函数小结(php下的转义字符串)
2007/04/12 PHP
phpinfo的知识点总结
2019/10/10 PHP
浅谈PHP之ThinkPHP框架使用详解
2020/07/21 PHP
JavaScript 参数中的数组展开 [译]
2012/09/21 Javascript
Javascript跨域请求的4种解决方式
2013/03/17 Javascript
jquery及原生js获取select下拉框选中的值示例
2013/10/25 Javascript
js字符串日期yyyy-MM-dd转化为date示例代码
2014/03/06 Javascript
jQuery选择器源码解读(八):addCombinator函数
2015/03/31 Javascript
jQuery与getJson结合的用法实例
2015/08/07 Javascript
Bootstrap基本样式学习笔记之标签(5)
2016/12/07 Javascript
IntersectionObserver API 详解篇
2016/12/11 Javascript
用jQuery.ajaxSetup实现对请求和响应数据的过滤
2016/12/20 Javascript
基于jquery二维码生成插件qrcode
2017/01/07 Javascript
vue图片加载与显示默认图片实例代码
2017/03/16 Javascript
JavaScript数据结构之二叉树的遍历算法示例
2017/04/13 Javascript
JS一个简单的注册页面实例
2017/09/05 Javascript
JavaScript设计模式之工厂模式和抽象工厂模式定义与用法分析
2018/07/26 Javascript
Vue实现剪贴板复制功能
2019/12/31 Javascript
基于JavaScript实现控制下拉列表
2020/05/08 Javascript
JavaScript中数组去重的5种方法
2020/07/04 Javascript
python连接池实现示例程序
2013/11/26 Python
详解Django 中是否使用时区的区别
2018/06/14 Python
Python 获取div标签中的文字实例
2018/12/20 Python
python中Lambda表达式详解
2019/11/20 Python
CSS3 创建网页动画实现弹跳球动效果
2018/10/30 HTML / CSS
加拿大时尚潮流大码女装购物网站:Addition Elle
2018/04/02 全球购物
TripAdvisor斯洛伐克:阅读评论、比较价格和酒店预订
2018/04/25 全球购物
Prototype是怎么扩展DOM的
2014/10/01 面试题
求职简历自荐信范文
2013/10/21 职场文书
党员违纪检讨书
2014/02/18 职场文书
2014年三万活动总结
2014/04/26 职场文书
社会稳定风险评估方案
2014/06/02 职场文书
企业安全生产检查制度
2015/08/06 职场文书
CocosCreator ScrollView优化系列之分帧加载
2021/04/14 Python
Redis6.0搭建集群Redis-cluster的方法
2021/05/08 Redis
mybatis 获取无数据的字段不显示的问题
2021/07/15 Java/Android