Сейчас мы с вами разберем более продвинутые вещи при работе с регулярными выражениями 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
Скоро появится.