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据option的value值快速设定初始的selected选项
Aug 13 Javascript
Javascript 强制类型转换函数
May 17 Javascript
Javascript 检测、添加、移除样式(className)函数代码
Sep 08 Javascript
js和as的稳定传值问题解决
Jul 14 Javascript
jQuery 借助插件Lavalamp实现导航条动态美化效果
Sep 27 Javascript
JavaScript实现的石头剪刀布游戏源码分享
Aug 22 Javascript
Javascript原型链的原理详解
Jan 05 Javascript
jquery.validate使用详解
Jun 02 Javascript
详解vue-router和vue-cli以及组件之间的传值
Jul 04 Javascript
通过seajs实现JavaScript的模块开发及按模块加载
Jun 06 Javascript
微信小程序云函数添加数据到数据库的方法
Mar 04 Javascript
JS箭头函数和常规函数之间的区别实例分析【 5 个区别】
May 27 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使用指定字符列表生成随机字符串的方法
2015/04/18 PHP
PHP SPL标准库之数据结构堆(SplHeap)简单使用实例
2015/05/12 PHP
php操作xml并将其插入数据库的实现方法
2016/09/08 PHP
PHP入门教程之数学运算技巧总结
2016/09/11 PHP
在php7中MongoDB实现模糊查询的方法详解
2017/05/03 PHP
javascript中获取选中对象的类型
2007/04/02 Javascript
多浏览器支持的右下角浮动窗口
2010/04/01 Javascript
jquery load事件(callback/data)使用方法及注意事项
2013/02/06 Javascript
Extjs407 getValue()和getRawValue()区别介绍
2013/05/21 Javascript
JS对img标签进行优化使用onerror显示默认图像
2014/04/24 Javascript
jQuery过滤HTML标签并高亮显示关键字的方法
2015/08/07 Javascript
深入理解Angularjs向指令传递数据双向绑定机制
2016/12/31 Javascript
Bootstrap响应式表格详解
2017/05/23 Javascript
Angular 5.0 来了! 有这些大变化
2017/11/15 Javascript
Vue封装一个简单轻量的上传文件组件的示例
2018/03/21 Javascript
jQuery使用动画队列自定义动画操作示例
2018/06/16 jQuery
详解为什么Vue中不要用index作为key(diff算法)
2020/04/04 Javascript
[29:10]Ti4 冒泡赛第二天 NEWBEE vs Titan 3
2014/07/15 DOTA
python实现代码行数统计示例分享
2014/02/10 Python
Python中的两个内置模块介绍
2015/04/05 Python
Python获取指定字符前面的所有字符方法
2018/05/02 Python
win7+Python3.5下scrapy的安装方法
2018/07/31 Python
python画柱状图--不同颜色并显示数值的方法
2018/12/13 Python
python3爬虫怎样构建请求header
2018/12/23 Python
python爬虫开发之使用python爬虫库requests,urllib与今日头条搜索功能爬取搜索内容实例
2020/03/10 Python
增大python字体的方法步骤
2020/07/05 Python
多个版本的python共存时使用pip的正确做法
2020/10/26 Python
Django与AJAX实现网页动态数据显示的示例代码
2021/02/24 Python
善意的谎言事例
2014/02/15 职场文书
父母对孩子说的话
2014/04/12 职场文书
学校就业推荐信范文
2014/05/19 职场文书
2014医学院领导班子对照检查材料思想汇报
2014/09/19 职场文书
《穷人》教学反思
2016/02/19 职场文书
人民币使用说明书
2019/04/17 职场文书
python文件名批量重命名脚本实例代码
2021/04/22 Python
springboot项目以jar包运行的操作方法
2021/06/30 Java/Android