正则表达式“捕获组"概念

266 阅读2分钟

问题描述:

最近一直在刷面试题,看到这位大佬提到“查找字符串中出现最多的字符和个数”题目: 

作者:寻找海蓝96
链接:https://juejin.cn/post/6844903940786487309


abbcccddddd -> 字符最多的是d,出现了5次

let str = "abcabcabcbbccccc";
let num = 0;
let char = '';

 // 使其按照一定的次序排列
str = str.split('').sort().join('');
// "aaabbbbbcccccccc"

// 定义正则表达式
let re = /(\w)\1+/g;
str.replace(re,($0,$1) => {
    if(num < $0.length){
        num = $0.length;
        char = $1;        
    }
});
console.log(`字符最多的是${char},出现了${num}次`);
其中,对 ”\1"感觉一头雾水,所以查阅一些资料,最后把这个问题搞明白了

探索过程

什么是捕获组?

    捕获组就是把正则表达式中子表达式匹配的内容,保存到内存中以数字编号或显式命名的组里,方便后面引用。当然,这种引用既可以是在正则表达式内部,也可以是在正则表达式外部。

1: () 捕获组/go+/以上的正则表达式表示一个字母g后面跟上一个或者多个字母o,他能匹配go或者goooo。
但是如果我们想+不只是运用到字母o上,而是运用到go这个整体上怎么办呢?办法就是给go加括号:/(go)+/为了全局匹配以及不考虑大小写,我们接下来会给我们的正则加上ig,这两个flag
let reg = /(go)+/ig;'go is g gogo'.match(reg); //["go", "gogo"]
在上面的例子里面“(go)”就形成了一个捕获组(capturing group)。

捕获组可以通过从左到右计算其开括号来编号 。

例如,在表达式 (A)(B(C)) 中,存在四个这样的组:

0

(A)(B(C))

1

(A)

2

(B(C))

3

(C)

组零始终代表整个表达式
1、之所以这样命名捕获组是因为在匹配中,保存了与这些组匹配的输入序列的每个子序列。捕获的子序列稍后可以通过 Back 引用(反向引用) 在表达式中使用,也可以在匹配操作完成后从匹配器检索。 
2、Back 引用 是说在后面的表达式中我们可以使用组的编号来引用前面的表达式所捕获到的文本序列。注意:反向引用,引用的是前面捕获组中的文本而不是正则,也就是说反向引用处匹配的文本应和前面捕获组中的文本相同,这一点很重要。 


探索结果

/(\w)\1+/g
(\w):全局查找字符串内的单词字符
\1+:重复利用第1个捕获组,捕获相同字符

// "aaabbbbbcccccccc"最后捕获结果为:
aaa
bbbbb
cccccccc



参考链接:

www.cnblogs.com/zhaoshujie/…

www.jb51.net/article/160…


到这里就完事了!!!