正则捕获组

分组类型

有四种分组类型

  • 捕获型()
  • 非捕获型(?:)
  • 正向前瞻型(?=)
  • 反向前瞻型(?!)

捕获型

  • 分组
    下面的正则表达式匹配dotdotdot
/dotdotdot/

更优雅的写法是将其分组,由一对圆括号包裹的小整体称为分组

/(dot){3}/
  • 候选
    一个分组中可以有多个候选表达式,用|分隔,|意为“或”
var reg = /I love (apple|orange|banana)/
reg.test('I love apple')//true
reg.test('I love orange')//true
reg.test('I love banana')//true
reg.test('I love popcorn')//false
  • 捕获与引用
    被正则表达式匹配到的字符串会被暂存起来,其中分组捕获的串从1开始编号,$1表示第一个被捕获的串,$2是第二个,以此类推,我们可以引用这些串。
var reg = /(\d{4})-(\d{2})-(\d{2})/
var data = '2017-10-24'
reg.test(data)
RegExp.$1//2017
RegExp.$2//10
RegExp.$3//24
  • 与replace配合
    String.prototype.replace方法的传参中可以直接引用被捕获的串。比如我们想将日期10.24/2017改为2017-10-24
var reg = /(\d{2})\.(\d{2})\/(\d{4})/
var data = '10.24/2017'
data = data.replace(reg, '$3-$1-$2')
console.log(data)//2017-10-24

给replace传递迭代函数可以优雅地解决一些问题
将违禁词转换为等字数的星号是一个常见的需求,比如文本是dot is a doubi,其中dotdoubi是违禁词,转换后应为*** is a *****

var reg = /(dot|doubi)/g
var str = 'dot is a doubi'
str = str.replace(reg, function (word) {
    return word.replace(/./g, '*')
})
console.log(str)//*** is a *****

replace与正则捕获组匹配还有一个常见用法,将浮点数左边的数从右向左每三位添加一个逗号

function commafy(num) {
    return num.toString().replace(/(\d)(?=(\d{3})+\.)/g, function ($2) {
        return $2 + ','
    })
}
console.log(commafy(1200000000.11))//1,200,000,000.11
console.log(commafy(123246723749.213769283))//123,246,723,749.21378

其中正则表达式部分如下,/(\d)(?=(\d{3})+\.)/g
匹配全局中,数字后面跟随的是(以.结尾的、三个数字的分组至少有一组)的串

  • 嵌套分组的捕获
    如果碰到类似/((dot) is (a (doubi)))/这种嵌套分组,捕获的顺序是什么呢?
var reg = /((dot) is (a (doubi)))/
var str = 'dot is a doubi'
reg.test(str)//true
console.log(RegExp.$1)//dot is a doubi
console.log(RegExp.$2)//dot
console.log(RegExp.$3)//a doubi
console.log(RegExp.$4)//doubi

从以上结果可看出,规则是以左括号出现的顺序进行捕获。

  • 反向引用
    正则表达式里可以进行反向引用
var reg = /(\w{3}) is \1/
console.log(reg.test('dot is dot'))//true
console.log(reg.test('dolby is dolby'))//false
console.log(reg.test('dot is tod'))//false
console.log(reg.test('dolby is dlboy'))//false

\1引用了第一个被分组所捕获的串,本例中即(\w{3}),表达式是动态决定的,如果编号越界了会被当成普通的表达式

var reg = /(\w{3}) is \3/
console.log(reg.test('dot is \3'))//true
console.log(reg.test('dolby is dolby'))//false

非捕获型分组

有时我们只是想分个组,并没有捕获的需求,这种情况下可以使用非捕获性分组,语法为(?:

var reg = /(?:\d{4})-(\d{2})-(\d{2})/
var date = '2017-10-24'
console.log(reg.test(date))//true
console.log(RegExp.$1)//10
console.log(RegExp.$2)//24

这个例子中,(?:\d{4})分组不会捕获任何串,所以$1为(\d{2})捕获的串

正向与反向前瞻型分组

但看名称概念有些模糊不清,可以理解为肯定表达式与否定表达式,前瞻型分组也不会捕获值

  • 正向前瞻
var reg = /dot is a (?=doubi)/
console.log(reg.test('dot is a doubi'))//true
console.log(reg.test('dot is a shadou'))//false

dot is a后面要跟上doubi才匹配成功

  • 反向前瞻
var reg = /dot is a (?!doubi)/
console.log(reg.test('dot is a doubi'))//false
console.log(reg.test('dot is a shadou'))//true

dot is a后面除了跟上doubi,都能匹配成功
前瞻型分组与非捕获型都不会捕获值,那么它们的区别是什么?

var str = 'dot is a doubi'
var reg = /dot is a (?:doubi)/
console.log(reg.test(str))//true
console.log(RegExp.$1)//无结果

reg = /dot is a (?=doubi)/
console.log(reg.test(str))//true
console.log(RegExp.$1)//无结果

reg = /(dot is a (?:doubi))/
console.log(reg.test(str))//true
console.log(RegExp.$1)//dot is a doubi

reg = /(dot is a (?=doubi))/
console.log(reg.test(str))//true
console.log(RegExp.$1)//dot is a

可以看出,非捕获型分组匹配到的串仍会被外层的捕获型分组捕获到,但前瞻型却不会,当你需要参考后面的值,又不想连它一起捕获时,前瞻型分组就派上用场了

关于正则表达式,更多请见我的博客

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,738评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,377评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,774评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,032评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,015评论 5 361
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,239评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,724评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,374评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,508评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,410评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,457评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,132评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,733评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,804评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,022评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,515评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,116评论 2 341

推荐阅读更多精彩内容