Сейчас мы с вами разберем более продвинутые вещи при работе с регулярными выражениями JavaScript.

Позитивный и негативный просмотр

Иногда нужно решить задачу такого типа: найти строку 'aaa' и заменить ее на '!', но только если после 'aaa' стоит 'x' (при этом 'x' не заменять).

Если мы попытаемся решить задачу 'в лоб', то у нас ничего не выйдет:

'aaax baaa'.replace(/xaaa/g, '!'); //вернет '! baaa', а хотели '!x baaa'

Нужен способ сказать, что 'x' не следует заменять. Делается это с помощью специальных скобок (?= ), которые просто смотрят, но не забирают с собой:

'xaaa baaa'.replace(/aaa(?=x)/g, '!'); //вернет 'x! baaa'

Скобки (?= ) называются позитивный просмотр вперед. Позитивный - так как 'x' (в нашем случае) должен быть - только тогда произойдет замена. Есть и негативный просмотр вперед - (?! ) - он, наоборот, говорит, что чего-то должно не быть:

//Если перед 'aaa' стоит НЕ 'x', тогда заменим на '!':
'xaaa baaa'.replace(/aaa(?!x)/g, '!'); //вернет 'xaaa b!'

К сожалению, в JavaScript, в отличие от других языков программирования, просмотра назад нет.

Метод replace - продвинутое использование

Метод replace вторым параметром может принимать не только строку, но и функцию, которая применится для каждого найденного совпадения.

Каждая подстрока, которую нашла регулярка, заменится на то, что вернет эта функция именно для этой подстроки.

В эту функцию можно передавать параметры: в первый параметр положится найденная строка, во второй параметр - первый карман, в третий параметр - второй карман и так далее - можно делать сколько параметров, сколько карманов в регулярном выражении.

В предпоследний параметр положится позиция найденного совпадения, а в последний - вся строка, по которой делается поиск.

где_ищем.replace(регулярка, function (найденное, карман1, карман2..., позиция, где ищем) {

});

Как это все работает - разберем на практических примерах. Давайте решим следующую задачу:

Задача: в строке даны числа, нужно заменить их на квадраты этих чисел. Для начала поэкспериментируем:

'2 3 4 5'.replace(/\d+/g, function (match) {
	alert(match);
});

Функция alert последовательно выведет 2, потом 3, 4 и 5. То есть в переменную match последовательно ложатся те строки, которые нашла регулярка.

Давайте решим задачу до конца - будем возводить match в квадрат и возвращать его с помощью return. Получится, что для найденной двойки вернется 4 и двойка заменится на эту четверку, для найденной тройки вернется 9 и тройка заменится на эту девятку - и так далее:

var result = '2 3 4 5'.replace(/\d+/g, function (match) {
	return match*match;
 });

alert(result);

Функция alert выведет '4 9 16 25' - то, что мы и хотели.

Еще задача: в строке даны конструкции вида '2+3=', нужно после равно вставить сумму этих чисел. Сама строка выглядит примерно так: '2+3= ... 25+50='. Опять давайте поэкспериментируем - разложим первое и второе слагаемые по отдельным карманам:

'2+3= ... 25+50='.replace(/(\d+)\+(\d+)=/g, function (match, match1, match2) {
	alert(match);
	alert(match1);
	alert(match2);
});

Сейчас мы увидим 6 алертов: первая тройка - это '2+3=', потом '2' (первый карман), потом '3' (второй карман), затем вторая тройка (для второго совпадения) - это '25+50=', потом '25' (первый карман), потом '50' (второй карман).

Давайте теперь окончательно решим задачу: для каждой найденной подстроки просуммируем первый и второй карманы, возьмем нулевой карман (найденную строку, например '2+3='), добавим к нему результат и вернем все это через return:

var result = '2+3= ... 25+50='.replace(/(\d+)\+(\d+)=/g, function (match, match1, match2) {
	var sum = match1 + match2;
	return match+sum; //здесь к '2+3=' прибавляется 5 - складываем как строки, для 25+50 аналогично
});

alert(result);

В результате alert выведет такую строку '2+3=5 ... 25+50=75' - для каждой найденной конструкции будет вычислена сумма.

Еще методы для работы с регулярками

Ниже мы разберем еще 3 полезных метода работы с регулярками: search, split и exec.

Метод search

Метод search принимает следующие параметры: где_ищем.replace(регулярка), а возвращает позицию первой найденной подстроки (если она не найдена - то вернет -1).

Метод split

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

Метод exec

Скоро появится.