Я не могу точно понять, как работает флаг g метода JavaScript string.match(regexp)

В книге «JavaScript: The Good Parts» метод string.match(regexp) объясняется следующим образом:

Метод match сопоставляет строку и регулярное выражение. Как это происходит, зависит от флага g. Если флаг g отсутствует, то результат вызова строки .match(regexp) будет таким же, как и вызов regexp .exec(string). Однако, если регулярное выражение имеет флаг g, то оно создает массив всех совпадений, но исключает захваченные группы:

Затем в книге приводится пример кода:

var text = '<html><body bgcolor=linen><p>This is <b>bold<\/b>!<\/p><\/body><\/html>';
var tags = /[^<>]+|<(\/?)([A-Za-z]+)([^<>]*)>/g;
var a, i;
a = text.match(tags);
for (i = 0; i < a.length; i += 1) {
    document.writeln(('// [' + i + '] ' + a[i]).entityify());
}
// The result is
// [0] <html>
// [1] <body bgcolor=linen>
// [2] <p>
// [3] This is
// [4] <b>
// [5] bold
// [6] </b>
// [7] !
// [8] </p>
// [9] </body>
// [10] </html>

Мой вопрос в том, что я не могу понять «но исключаю группы захвата».

В приведенном выше примере кода html в </html> находится в группе захвата. И почему он все еще включен в массив результатов?

А / в </html> тоже входит в группу захвата. И почему он включен в массив результатов?

Не могли бы вы объяснить «но исключает группы захвата» с помощью приведенного выше примера кода?

Большое спасибо!


person weilou    schedule 05.06.2012    source источник


Ответы (2)


В приведенном выше примере кода html в группе захвата. И почему он все еще включен в массив результатов?

Потому что это полное совпадение. Когда он говорит «но исключает группы захвата», он имеет в виду не полный результат совпадения, а только то, что содержимое групп захвата не повторяется в массиве. Если бы группы захвата были включены, вы бы увидели

// The result is
// [0] <html>
// [1]           // From the capture group; nothing here
// [2] html      // From the capture group
// [3]           // From the capture group; nothing here
// ...

И/в также находится в группе захвата. И почему он включен в массив результатов?

По той же причине, что и выше: это часть общего совпадения, и это то, что в результате; содержимое отдельных групп захвата — нет.

Это легче понять на более простом примере. Рассмотрим этот код:

var s = "test1 test2";
var re = /(test)(.)/g;
var r = s.match(re);
var i;
for (i = 0; i < r.length; ++i) {
    console.log("[" + i + "]: '" + r[i] + "'");
}

Поскольку регулярное выражение имеет флаг g, в массив включаются только полные совпадения, поэтому мы видим:

[0]: 'test1'
[1]: 'test2'

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

Если бы мы удалили флаг g, но ничего больше не изменили бы, то получили бы первое полное совпадение, за которым следовало бы содержимое двух групп захвата:

[0]: 'test1'    // The full match, including the stuff from each capture group
[1]: 'test'     // Capture group 0's contents
[2]: '1'        // Capture group 1's contents

Там первая запись — это полное совпадение; тогда вторая и третья — это содержимое групп захвата. Обратите внимание, что содержимое групп захвата

person T.J. Crowder    schedule 05.06.2012
comment
Большое спасибо! Ваш ответ правильный, подробный и полезный! - person weilou; 05.06.2012
comment
@WeiLou: :-) Спасибо! Рад, что помог. Лучший, - person T.J. Crowder; 05.06.2012

модификатор g предназначен для глобального применения регулярного выражения. Без него регулярное выражение соответствует и возвращает первое найденное совпадение. С его помощью он ищет и сопоставляет все вхождения в строке.

person Crayon Violent    schedule 05.06.2012