Понимание "глобального" RegExp - PullRequest
2 голосов
/ 15 декабря 2011

Ожидаемый вывод для "test".match(/[a-z]{0,}/g); должен содержать '', 't', 'e', 's', 't', 'te', 'es', 'st' и т. Д.

Однако я получаю только '' и 'test' с консоли.Что здесь происходит?

Ответы [ 6 ]

4 голосов
/ 15 декабря 2011

Ваше регулярное выражение соответствует полному тексту в первом проходе и пустой строке во втором проходе, вот почему.

К сожалению, что вы хотите, требует, чтобы механизм регулярных выражений поддерживал модификатор \G (IIRC), которого нет в регулярных выражениях ECMA 262.

2 голосов
/ 15 декабря 2011

Если вы ищете все словосочетания, вот код, над которым я работал:

<html>
<body>

<script type="text/javascript">
function removeDuplicateElement(arrayName) {
    var newArray=new Array();
    label: for(var i=0; i<arrayName.length;i++){
        for(var j=0; j<newArray.length;j++) {
            if(newArray[j]==arrayName[i]) 
                continue label;
        }
        newArray[newArray.length] = arrayName[i];
    }
    return newArray;
}

var all=new Array();
var str="test";
for (;str.length>0;str=str.substring(1,str.length)) {
    for (var i = 0; i<=str.length;i++){
        var patt1=new RegExp("([a-z]{"+i+","+i+"})", "g");
        all=all.concat(str.match(patt1));
    }
}

document.write(removeDuplicateElement(all));
</script>

</body>
</html>

Для «теста» он возвращает «, t, e, s, te,й, тес, тест, эс, ЭСТ.

1 голос
/ 15 декабря 2011

match возвращает массив совпадений, каждый из которых начинается после конца предыдущего совпадения. Если вместо этого вы используете "test".match(/[a-z]/g);, вы получите ["t", "e", "s", "t"] в результате. "t" соответствует, следующая вещь, которая соответствует после "t", это "e" ...

В вашем запросе регулярное выражение соответствует всей строке, поэтому оно выдает «test», после чего совпадает пустая строка, следующая за «test» (поскольку вы использовали {0,} вместо {1,}.

1 голос
/ 15 декабря 2011

Сопоставление строки с глобальным регулярным выражением всегда даст вам максимально длинные непересекающиеся подстроки.Первое самое длинное совпадение - это вся строка "test", а затем остается пустая строка "", что тоже совпадает.Вы можете достичь желаемого, сопоставляя несколько регулярных выражений с различными спецификаторами длины, например:

"test".match(/[a-z]{0}/g);
"test".match(/[a-z]{1}/g);
"test".match(/[a-z]{2}/g);
"test".match(/[a-z]{3}/g);
"test".match(/[a-z]{4}/g);

Конечно, это должно быть сделано более элегантно;Вы можете построить эти регулярные выражения динамически, например, используя new RegExp("[string]").Тем не менее, это не даст, например, "es" (хотя вы могли бы обойти это снова), но, согласно вашему вопросу, вы все равно не хотите получать этот матч.

1 голос
/ 15 декабря 2011

Если вы хотите создать эту функцию самостоятельно, вы можете попробовать что-то вроде:

String.prototype.fullMatch = function () {
    var matches = [""]; // "" is always a match

    function do_regex(str, startAt) {
        var len = str.length,
            i,
            j,
            regex,
            all_matches = [];

        for (i = startAt; i < len; i++) {
            regex = new RegExp("[a-z]{" + (i + 1) + "}", "g");
            all_matches = str.match(regex);
            for (j = 0; j < all_matches.length; j++) {
                matches.push(all_matches[j]);
            }
        }
    }

    for (var k = 0; k < this.length; k ++) {
        do_regex(this.substring(k), k);
    }

    return matches;  
};

console.log("test".fullMatch()); // ["", "t", "e", "s", "t", "te", "st", "tes", "test", "es", "est"]
1 голос
/ 15 декабря 2011

Вы получаете только ["", "test"], потому что квантификатор {0,} будет соответствовать либо нулю, либо любому количеству букв (точно так же, как *) и является жадным (так же, как *), поэтому он соответствует максимальному числу, которое он может найти (и ноль).

...