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 相关文章推荐
我见过最全的个人js加解密功能页面
Dec 12 Javascript
JavaScript高级程序设计(第3版)学习笔记11 内建js对象
Oct 11 Javascript
jQuery实现table隔行换色和鼠标经过变色的两种方法
Jun 15 Javascript
jquery text()方法取标签中的文本
Jul 25 Javascript
js简单实现点击左右运动的方法
Apr 10 Javascript
Jquery组件easyUi实现选项卡切换示例
Aug 23 Javascript
响应式表格之固定表头的简单实现
Aug 26 Javascript
使用AngularJS对表单提交内容进行验证的操作方法
Jul 12 Javascript
Vue 中使用 CSS Modules优雅方法
Apr 09 Javascript
微信小程序上传图片功能(附后端代码)
Jun 19 Javascript
Openlayers+EasyUI Tree动态实现图层控制
Sep 28 Javascript
react国际化react-intl的使用
May 06 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 用checkbox一次性删除多条记录的方法
2010/02/23 PHP
php遍历目录输出目录及其下的所有文件示例
2014/01/27 PHP
PHP根据传来的16进制颜色代码自动改变背景颜色
2014/06/13 PHP
如何在Laravel5.8中正确地应用Repository设计模式
2019/11/26 PHP
php把文件设置为插件的技巧方法
2020/02/03 PHP
Jquery给基本控件的取值、赋值示例
2014/05/23 Javascript
jQuery调取jSon数据并展示的方法
2015/01/29 Javascript
解决bootstrap中modal遇到Esc键无法关闭页面
2015/03/09 Javascript
初识Node.js
2015/03/20 Javascript
JavaScript编写Chrome扩展实现与浏览器的交互及时间通知
2016/05/16 Javascript
javascript 数组去重复(在线去重工具)
2016/12/17 Javascript
Bootstrap导航中表单简单实现代码
2017/03/06 Javascript
推荐三款不错的图片压缩上传插件(webuploader、localResizeIMG4、LUploader)
2017/04/21 Javascript
vue中设置、获取、删除cookie的方法
2018/09/21 Javascript
使用Python的Flask框架构建大型Web应用程序的结构示例
2016/06/04 Python
python函数中return后的语句一定不会执行吗?
2017/07/06 Python
Django开发的简易留言板案例详解
2018/12/04 Python
Python中base64与xml取值结合问题
2019/12/22 Python
Django之form组件自动校验数据实现
2020/01/14 Python
Python使用Turtle模块绘制国旗的方法示例
2021/02/28 Python
详解html5 shiv.js和respond.min.js
2018/01/24 HTML / CSS
LTD Commodities:礼品,独特发现,家居装饰,家用器皿
2017/08/11 全球购物
新西兰演唱会和体育门票网站:Ticketmaster新西兰
2017/10/07 全球购物
美国益智玩具购物网站:Fat Brain Toys
2017/11/03 全球购物
回馈慈善的设计师太阳镜:DIFF eyewear
2019/10/17 全球购物
eDreams德国:南欧领先的在线旅游公司
2020/12/07 全球购物
某/etc/fstab文件中的某行如下: /dev/had5 /mnt/dosdata msdos defaults,usrquota 1 2 请解释其含义
2013/09/18 面试题
党政领导班子群众路线对照检查材料思想汇报
2014/09/27 职场文书
先进工作者事迹材料
2014/12/23 职场文书
党建工作目标管理责任书
2015/01/29 职场文书
黑白记忆观后感
2015/06/18 职场文书
廉洁自律承诺书2016
2016/03/25 职场文书
文明医院的标语集锦!
2019/07/24 职场文书
一道JS算法面试题——冒泡、选择排序
2021/04/21 Javascript
python脚本框架webpy模板赋值实现
2021/11/20 Python
三种方式清除vue路由跳转router-link的历史记录
2022/04/10 Vue.js