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 弹出层组件(升级版)
May 12 Javascript
js去字符串前后空格5种实现方法及比较
Apr 03 Javascript
jQuery动态设置form表单的enctype值(实现代码)
Jul 04 Javascript
让jQuery Mobile不显示讨厌loading界面的方法
Feb 19 Javascript
原生js实现addClass,removeClass,hasClass方法
Apr 27 Javascript
js检查是否关闭浏览器的方法
Aug 02 Javascript
微信小程序 获取相册照片实例详解
Nov 16 Javascript
微信小程序学习(4)-系统配置app.json详解
Jan 12 Javascript
AngularJS ng-repeat指令及Ajax的应用实例分析
Jul 06 Javascript
详解require.js配置路径的用法和css的引入
Sep 06 Javascript
vue+elementui 实现新增和修改共用一个弹框的完整代码
Jun 08 Vue.js
三种方式清除vue路由跳转router-link的历史记录
Apr 10 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
[原创]效率较高的php下读取文本文件的代码
2008/07/02 PHP
php 破解防盗链图片函数
2008/12/09 PHP
php页面防重复提交方法总结
2013/11/25 PHP
利用php下载xls文件(自己动手写的)
2014/04/18 PHP
CodeIgniter启用缓存和清除缓存的方法
2014/06/12 PHP
PHP 5.6.11 访问SQL Server2008R2的几种情况详解
2016/08/08 PHP
PHP连接MySQL数据库操作代码实例解析
2020/07/11 PHP
Aliyun Linux 编译安装 php7.3 tengine2.3.2 mysql8.0 redis5的过程详解
2020/10/20 PHP
jQuery 工具函数学习资料
2010/04/29 Javascript
jQuery对表单元素的取值和赋值操作代码
2011/05/19 Javascript
JavaScript改变CSS样式的方法汇总
2015/05/07 Javascript
JQuery中DOM事件合成用法实例分析
2015/06/13 Javascript
Jquery实现简单的轮播效果(代码管用)
2016/03/14 Javascript
javascript实现抽奖程序的简单实例
2016/06/07 Javascript
原生js实现查询天气小应用
2016/12/09 Javascript
JavaScript之RegExp_动力节点Java学院整理
2017/06/29 Javascript
vue-cli监听组件加载完成的方法
2018/09/07 Javascript
JS如何定义用字符串拼接的变量
2020/07/11 Javascript
[01:56]《DOTA2》中文配音CG
2013/04/22 DOTA
[38:39]完美世界DOTA2联赛循环赛 IO vs GXR BO2第二场 11.04
2020/11/05 DOTA
Python正则替换字符串函数re.sub用法示例
2017/01/19 Python
Python实现利用最大公约数求三个正整数的最小公倍数示例
2017/09/30 Python
python中学习K-Means和图片压缩
2017/11/20 Python
python机器学习理论与实战(五)支持向量机
2018/01/19 Python
django中静态文件配置static的方法
2018/05/20 Python
Python3实现的判断环形链表算法示例
2019/03/07 Python
python3.x提取中文的正则表达式示例代码
2019/07/23 Python
wxPython绘图模块wxPyPlot实现数据可视化
2019/11/19 Python
python实现学生管理系统开发
2020/07/24 Python
Python从文件中读取数据的方法步骤
2020/11/18 Python
整理HTML5的一些新特性与Canvas的常用属性
2016/01/29 HTML / CSS
美国羽绒床上用品第一品牌:Pacific Coast
2018/08/25 全球购物
Godiva巧克力英国官网:比利时歌帝梵巧克力
2018/08/28 全球购物
员工自我工作评价
2015/03/06 职场文书
超级礼物观后感
2015/06/15 职场文书
法制主题班会教案
2015/08/13 职场文书