正则 #分组# #捕获#

199 阅读2分钟

遇到的一道题引发的思考:

Q:给定字符串 str,检查其是否包含连续重复的字母(a-zA-Z),包含返回 true,否则返回 false

答案提示一下,使用正则的分组捕获来解决其实挺简单的,答案一会放出.

所以先来复盘下正则表达式的分组捕获:

(x):捕获组: 匹配x并记住匹配项。例如,/(foo)/匹配并记住“foo bar”中的“foo” 
正则表达式可以有多个捕获组。结果,匹配通常在数组中捕获的组,该数组的成员与捕获组中左括号的顺序相同。这通常只是捕获组本身的顺序。当捕获组被嵌套时,这一点非常重要。使用结果元素的索引 ([1], ..., [n]) 或从预定义的 RegExp 对象的属性 ($1, ..., $9).

有点小绕口,我们直接看demo:

demo1:

let reg = /(\d{4})-(\d{2})-(\d{2})  			//定义一个正则,中间由三个()括号组成,相当于分成了三组,并且默认捕获,可以使用RegExp.$n(n=1开始)获取
console.log(reg.test('2020-10-14'))  			// true
console.log(RegExp.$1)  			 	// 2020
console.log(RegExp.$2)  				// 10
console.log(RegExp.$3)  				// 14
console.log(RegExp.$4)  				// "" 因为只定义了三个分组,$4大于分组数量,返回""

demo2:

let str = 'lol lol '
let nStr = str.replace(/(lo)l/g,'$1oo')		// '$1oo' === 'looo' $1就相当于括号匹配内的内容,类似使用了变量
console.log(nStr)    				//"looo looo "

demo3: 非捕获 (?:regex)

let reg = /(?:\d{4})-(\d{2})-(\d{2})/    //注意跟demo1的区别就是多了个?:,代表非捕获,或者理解为匹配 'd{4}' 但是不记住匹配项
reg.test('2020-10-14')  		// true
console.log(RegExp.$1)  		// 10

所以本文最初的答案就是下面这样很简单的使用分组([a-zA-Z])再加上捕获\1(对就是这么神奇,上面一直写的是1,1,2,test里面就改成了\1,\2等)组成的两个连续重复的字母组成的正则,具体看如下:

A:

function containsRepeatingLetter(str) {
   return /([a-zA-Z])\1/.test(str)
}

如果理解了上面几个例子,我相信其他的向前断言x(?=y),向前否定断言x(?!y),向后断言(?<=y)x,向后否定断言(?<!y)x大家应该就不会混淆了

最后收尾

let myBankSavings = '123456789';
myBankSavings.replace(/(\d)(?=(?:\d{3})+$)/g,'$1,')   //格式化我的存款,123,456,789