Можно задавать не только группы символов, которые должны совпасть, но и количество таких совпадений. Для этого предназначены квантификаторы. Сразу отметим, что квантификаторы являются метасимволами, то есть для их поиска они должны быть экранированы, если только они не находятся в описании класса символов. Квантификаторы ставятся после символа или класса, число повторений которого они задают. Так, для поиска целого числа вполне подойдёт шаблон [+-]?\d+, где ‘+’ внутри класса – просто литеральный символ, ‘?’ – квантификатор, который позволяет совпадать классу [+-] не более одного раза (то есть либо 0, либо 1), а последний ‘+’ - квантификатор, который задаёт повторение класса \d как минимум один раз.
Пример Js56
Так что код
var re = /[+-]?\d+/g;
var st = "-32 +4 00989 09. -1-1"
alert(st.match(re));
выведет
Пример Js57
Ежели требуется задать повторение группы символов, группу необходимо заключить в скобки. Так, код
var re = /[+-]?\d+(\.\d+)?/g;
var st = "+7.15 03.08"
alert(st.match(re));
ищет вещественные числа:
Квантификатор ‘*’ задаёт повторение произвольное число раз, в том числе 0. Так, код
Пример Js58
var re = /<.*>/g;
var st = "<a href='www.apmath.spbu.ru'>Our Faculty<\n>"
alert(st.match(re));
выведет
Однако код
Пример Js59
var re = /<.*>/g;
var st = "<a href='www.apmath.spbu.ru'>Our Faculty</a>"
alert(st.match(re));
выведет
Дело в том, что .* совпадает с любой последовательностью символов (кроме ‘\n’, конечно).
При этом всякий квантификатор стремится совпасть с максимально возможным количеством символов. Такие квантификаторы называют жадными. Можно ограничить квантификаторы, задав режим поиска минимального совпадения. Такие квантификаторы называют ленивыми, и они отличаются от жадных указанием знака вопроса в конце: ‘*?’, ‘+?’, ‘??”.
Пример Js60
Так, код
var re = /<.*?>/g;
var st = "<a href='www.apmath.spbu.ru'>Our Faculty</a>"
alert(st.match(re));
выводит ожидаемое
Можно также задавать произвольное количество совпадений при помощи конструкции “{m,n}”, которая задаёт количество повторений от m до n. Если не указать n, то есть выражение имеет вид “{m,}”, то задаётся число повторений не менее m. Конструкция “{m}” задаёт ровно m совпадений. Заметим, фигурные скобки, равно как квадратные и круглые, являются метасимволами.
Захват
Вернёмся к примеру
Пример Js61
var re = /[+-]?\d+(\.\d+)?/g;
var st = "+7.15 03.08"
alert(st.match(re));
и уберём модификатор /g:
Пример Js62
var re = /[+-]?\d+(\.\d+)?/;
var st = "+7.15 03.08"
alert(st.match(re));
Тогда вывод будет таким:
Метод match на самом деле возвращает массив, нулевой элемент которого содержит полное совпадение, а последующие элементы отражают содержимое круглых скобок, скобки при этом нумеруются по положению открывающих скобок слева направо, с единицы.
Пример Js63
Так, код
var re = /((\d)(\d))/;
var st = "74"
alert(st.match(re));
вернёт
Можно предотвратить захват, используя для группировки скобки вида “(?: )”, так, код
Пример Js64
var re = /((?:\d)(\d))/;
var st = "74"
alert(st.match(re));
вернёт
Зачем вообще использовать незахватывающие скобки? Да, в этом примере без них можно обойтись.
Пример Js65
Однако при задании повторения группы символов они необходимы. Кроме того, конструкция выбора “|” также заключается в скобки, например, здесь:
var re = /\d+(?:USD|EUR)/;
var st = "74USD vs. 40EUR"
alert(st.match(re));
конструкция “(?:USD|EUR)” совпадает либо с подстрокой ‘USD’, либо с подстрокой ‘EUR’. Подстроки могут содержать и метасимволы. Кстати, “|” – тоже метасимвол.
Внутри регулярного выражения также можно ссылаться на уже захваченные фрагменты. Например, \1 соответствует выражению, захваченному первыми скобками, \2 – вторыми, \{10} – десятыми.
Попробуйте объяснить, почему код
Пример Js66
var re = /^(11+)\1+$/;
var s = '1';
var res = '';
for (var i = 2; i < 100; i++) {
s += '1';
if (!re.test(s)) res += i + ' ';
}
alert(res);
выводит простые числа, меньшие ста:
Захват можно использовать и в выражениях замены. Там содержимое первых скобок обозначается $1, вторых - $2, и т.д вплоть до $9.
Например, переставить два соседних слова можно так:
Пример Js67
var re = /(\w+)\s+(\w+)/;
var s = "first second third";
alert(s.replace(re, "$2 $1"));
Что есть $1, $2? Это поля класса RegExp. Кроме того, поле index содержит позицию найденной подстроки, input – саму строку, в которой производился поиск, multiline – логическое значение, отражающее указание модификатора /m, lastMatch – совпадение, возвращаемое в нулевом элементе массива match, lastParen – содержимое последних захватывающих скобок, leftContext – всё до совпадения, rightContext – всё после. Эти поля устанавливаются только после успешного поиска.
Пример Js68
Для примера,
var re = /(\d+)\D(\d+)?\D(\d+)?/;
var s = "the |44|14| succession";
var res = '';
s.match(re);
res += 'input="' + RegExp.input + '"; ';
res += 'multiline="' + RegExp.multiline + '"; ';
res += 'lastMatch="' + RegExp.lastMatch + '"; ';
res += 'lastParen="' + RegExp.lastParen + '"; ';
res += 'leftContext="' + RegExp.leftContext + '"; ';
res += 'rightContext="' + RegExp.rightContext + '"; ';