时间: 2020-08-25|tag: 34次围观|0 条评论

分组类型

有四种分组类型

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

捕获型

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

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

/(dot){3}/
  • 候选
    一个分组中可以有多个候选表达式,用|分隔,|意为“或”
var reg = /I love (apple|orange|banana)/reg.test('I love apple')//truereg.test('I love orange')//truereg.test('I love banana')//truereg.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//2017RegExp.$2//10RegExp.$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)/gvar 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.11console.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)//trueconsole.log(RegExp.$1)//dot is a doubiconsole.log(RegExp.$2)//dotconsole.log(RegExp.$3)//a doubiconsole.log(RegExp.$4)//doubi

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

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

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

var reg = /(\w{3}) is \3/console.log(reg.test('dot is \3'))//trueconsole.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))//trueconsole.log(RegExp.$1)//10console.log(RegExp.$2)//24

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

正向与反向前瞻型分组

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

  • 正向前瞻
var reg = /dot is a (?=doubi)/console.log(reg.test('dot is a doubi'))//trueconsole.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'))//falseconsole.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))//trueconsole.log(RegExp.$1)//无结果reg = /dot is a (?=doubi)/console.log(reg.test(str))//trueconsole.log(RegExp.$1)//无结果reg = /(dot is a (?:doubi))/console.log(reg.test(str))//trueconsole.log(RegExp.$1)//dot is a doubireg = /(dot is a (?=doubi))/console.log(reg.test(str))//trueconsole.log(RegExp.$1)//dot is a

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

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

文章转载于:https://www.jianshu.com/p/d771828f8fd4

原著是一个有趣的人,若有侵权,请通知删除

本博客所有文章如无特别注明均为原创。
复制或转载请以超链接形式注明转自起风了,原文地址《正则捕获组
   

还没有人抢沙发呢~