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 相关文章推荐
基于jQuery的获得各种控件Value的方法
Nov 19 Javascript
使用jQuery避免鼠标双击的解决方案
Aug 21 Javascript
动态显示可输入的字数提示还可以输入的字数
Apr 01 Javascript
jquery中$(#form :input)与$(#form input)的区别
Aug 18 Javascript
JS实现兼容性好,自动置顶的淘宝悬浮工具栏效果
Sep 18 Javascript
一种Javascript解释ajax返回的json的好方法(推荐)
Jun 02 Javascript
浅析JavaScriptSerializer类的序列化与反序列化
Nov 22 Javascript
Bootstrap CSS组件之大屏幕展播
Dec 17 Javascript
对象不支持indexOf属性或方法的解决方法(必看)
May 28 Javascript
React Native中TabBarIOS的简单使用方法示例
Oct 13 Javascript
微信小程序时间控件picker view使用详解
Dec 28 Javascript
微信小程序点击列表跳转到对应详情页过程解析
Sep 26 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 翻页 实例代码
2009/08/07 PHP
php !function_exists("T7FC56270E7A70FA81A5935B72EACBE29"))代码解密
2011/01/07 PHP
PHP OPP机制和模式简介(抽象类、接口和契约式编程)
2014/06/09 PHP
ThinkPHP之R方法实例详解
2014/06/20 PHP
php+memcache实现的网站在线人数统计代码
2014/07/04 PHP
JavaScript 给汉字排序实例代码
2008/06/28 Javascript
JavaScript实现拼音排序的方法
2012/11/20 Javascript
JS将表单导出成EXCEL的实例代码
2013/11/11 Javascript
javascript为下拉列表动态添加数据项
2014/05/23 Javascript
javascript判断并获取注册表中可信任站点的方法
2015/06/01 Javascript
jQuery UI插件实现百度提词器效果
2016/11/21 Javascript
jquery Ajax 全局调用封装实例详解
2017/01/16 Javascript
BootstrapValidator实现注册校验和登录错误提示效果
2017/03/10 Javascript
JS实现前端页面的搜索功能
2018/06/12 Javascript
angularJS1 url中携带参数的获取方法
2018/10/09 Javascript
Vue.js轮播图走马灯代码实例(全)
2019/05/08 Javascript
python打开网页和暂停实例
2014/09/30 Python
python交互式图形编程实例(一)
2017/11/17 Python
Python使用pickle模块实现序列化功能示例
2018/07/13 Python
Python后台开发Django会话控制的实现
2019/04/15 Python
python中matplotlib条件背景颜色的实现
2019/09/02 Python
在pycharm中创建django项目的示例代码
2020/05/28 Python
Python如何爬取b站热门视频并导入Excel
2020/08/10 Python
python七种方法判断字符串是否包含子串
2020/08/18 Python
Pycharm中使用git进行合作开发的教程详解
2020/11/17 Python
Aerosoles爱柔仕官网:美国舒软女鞋品牌
2017/07/17 全球购物
世界首屈一指的在线男士内衣权威:HisRoom
2017/08/05 全球购物
应届生妇产科护士求职信
2013/10/27 职场文书
学生励志演讲稿
2014/01/06 职场文书
副董事长岗位职责
2014/04/02 职场文书
小学感恩节活动策划方案
2014/10/06 职场文书
2015年健康教育工作总结
2015/04/10 职场文书
电话营销开场白
2015/05/29 职场文书
红色革命电影观后感
2015/06/18 职场文书
2019自荐信该如何写呢?
2019/07/05 职场文书
html+css实现环绕倒影加载特效
2021/07/07 HTML / CSS