文章25
标签17
分类3

正则表达式的反向引用

今天遇到了一道题,他是这样的:

题目描述

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

实例

输入:'rattler'
输出:true


我的解决方式是这样的,循环检测每一个字符和它下一个字符是否相同,从第一个字符开始,所以最后一个字符不需要检测,代码:

function containsRepeatingLetter(str) {
    for(var i = 0;i < str.length;i++){
        if(i !== str.length-1){
            if(str[i] == str[i+1] && /[a-zA-Z]/.test(str[i]) && /[a-zA-Z]/.test(str[i+1])){
                return true;
            }
        }
    }
    return false;
}

事实证明,这个代码是通过了验证的,但是我在查看其它人的代码时却发现一个以前从来没有研究过的东西

反向引用

首先给出地址:http://www.cnblogs.com/-ShiL/archive/2012/04/06/Star201204061009.html
重点看其中的2.1节,大致就可以理解

源字符串:abcdebbcde
正则表达式:([ab])\1
对于正则表达式“([ab])\1”,捕获组中的子表达式“[ab]”虽然可以匹配“a”或者“b”,但是捕获组一旦匹配成功,反向引用的内容也就确定了。如果捕获组匹配到“a”,那么反向引用也就只能匹配“a”,同理,如果捕获组匹配到的是“b”,那么反向引用也就只能匹配“b”。由于后面反向引用“\1”的限制,要求必须是两个相同的字符,在这里也就是“aa”或者“bb”才能匹配成功。
考察一下这个正则表达式的匹配过程,在位置0处,由“([ab])”匹配“a”成功,将捕获的内容保存在编号为1的组中,然后把控制权交给“\1”,由于此时捕获组已记录了捕获内容为“a”,“\1”也就确定只有匹配到“a”才能匹配成功,这里显然不满足,“\1”匹配失败,由于没有可供回溯的状态,整个表达式在位置0处匹配失败。
正则引擎向前传动,在位置5之前,“([ab])”一直匹配失败。传动到位置5处时,,“([ab])”匹配到“b”,匹配成功,将捕获的内容保存在编号为1的组中,然后把控制权交给“\1”,由于此时捕获组已记录了捕获内容为“b”,“\1”也就确定只有匹配到“b”才能匹配成功,满足条件,“\1”匹配成功,整个表达式匹配成功,匹配结果为“bb”,匹配开始位置为5,结束位置为7。
扩展一下,正则表达式“([a-z])\1{2}”也就表达连续三个相同的小写字母。

所以整段代码可以缩减为:

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

0 评论