Почему не работает "жадный" режим RegExp? - PullRequest
0 голосов
/ 03 февраля 2012

Я не понимаю, поведение.У меня есть такой пример, нужно ловить html комментарий.

var str = '.. <!--My -- comment test--> ';

var regex1 = /<!--[.]*-->/g;
var regex2 = /<!--.*-->/g;

alert(str.match(regex1));      // null
alert(str.match(regex2));      // <!--My -- comment test--> 

Второй регулярное выражение regex2 работает нормально, выводит именно то, что нужно.Первый показывает null.И я не понимаю разницу.Регулярные выражения <!--[.]*--> и <!--.*--> означают одно и то же - «после <!-- принимайте ЛЮБОЙ символ, кроме символа новой строки в количестве от 0 до максимально возможного количества, и заканчивайте -->».Но для второго это работает, а для первого нет.Почему?

UPD.Я прочитал комментарии и получил обновление.

var str3 = '.. <!--Mycommenttest--> ';
var str4 = '.. <!--My comment test--> ';

var regex3 = /<!--[\w]*-->/g;
var regex4 = /<!--[\s\S]*-->/g;

alert(str.match(regex3));         // <!--Mycommentstest-->
alert(str.match(regex4));         // <!-- My comment test -->

Так что можно использовать ограниченные совпадающие переменные для сопоставления чего угодно.Так какой путь следует использовать для правильного использования RegExps?С [] или без них?Не могу получить разницу, оба дают правильный вывод.

Ответы [ 4 ]

5 голосов
/ 03 февраля 2012

Точка (.) не означает «что-нибудь» внутри класса символов.Зачем вам нужен класс персонажа, чтобы соответствовать чему-либо?

3 голосов
/ 04 февраля 2012

Сокращения класса символов, такие как \w, \d и \s, означают те же самые внутренние классы символов, что и out, но метасимволы, такие как ., обычно теряют свои специальные значения внутри классов символов. Вот почему /<!--[.]*-->/ не сработал, как вы ожидали: [.] соответствует литералу ..

Но /<!--.*-->/ на самом деле тоже не работает, поскольку . не соответствует символам новой строки. В большинстве разновидностей регулярных выражений вы используете однострочный режим, чтобы точка соответствовала всем символам , включая переводы строки, например: /<!--.*-->/s или this: (?s)<!--.*-->. Но JavaScript не поддерживает эту функцию, поэтому большинство людей вместо этого используют [\s\S], что означает «любой символ пробела или любой символ, который не пробел» - другими словами, любой символ.

Но это тоже неправильно, поскольку (как указал Джейсон в своем комментарии) он будет жадно сопоставлять все, начиная от первого <!-- до последнего -->, что может включать несколько отдельных комментариев и весь материал, не содержащий комментариев. между ними. Чтобы сделать это действительно правильно, вероятно, не стоит усилий. При использовании регулярных выражений для соответствия HTML, вы все равно должны сделать много упрощающих предположений; если вы не можете принять определенный уровень правильной формы, вы можете сдаться. В этом случае должно быть достаточно, чтобы квантификатор не был жадным:

var regex5 = /<!--[\s\S]*?-->/g;
3 голосов
/ 03 февраля 2012

выражения <!--[.]*--> и <!--.*--> означают одно и то же

Это не правильно.

Скобки [] обозначают класс символов, где любой символ в классе может быть сопоставлен. [.] - это класс символов, который содержит символ '.'. Сравните это с ., который является предопределенным классом символов, обозначаемым как «любой символ» (кроме ограничителей строки).

То, что вы соответствуете <!--[.]*-->, это либо пустой комментарий, либо комментарий, состоящий полностью из символов .. И то, что вы сопоставляете с <!--.*-->, это либо пустой комментарий, либо комментарий, заполненный любым символом, кроме переносов строк.

2 голосов
/ 03 февраля 2012

Первое не потому, что это не значит то же самое. Первый означает совпадение с символом точки. Символ точки не является общим совпадением, если помещен в набор []. (и если подумать, это имеет смысл: почему вы хотите сопоставить что-либо внутри набора ограниченных совпадающих переменных)

...