заменяется текстом, который совпал с первой группой,
>$2
– со второй группой, и так далее, до
>$9
. Всё совпадение целиком содержится в переменной
>$&
.
Также можно в качестве второго аргумента передавать и функцию. Для каждой замены будет вызвана функция, аргументами которой будут найденные группы (и вся совпадающая часть строки целиком), а её результат будет вставлен в новую строку.
Простой пример:
>var s = "the cia and fbi";
>console.log(s.replace(/\b(fbi|cia)\b/g, function(str) {
> return str.toUpperCase();
>}));
>// → the CIA and FBI
А вот более интересный:
>var stock = "1 lemon, 2 cabbages, and 101 eggs";
>function minusOne(match, amount, unit) {
> amount = Number(amount) - 1;
> if (amount == 1) // остался только один, удаляем 's' в конце
> unit = unit.slice(0, unit.length - 1);
> else if (amount == 0)
> amount = "no";
> return amount + " " + unit;
>}
>console.log(stock.replace(/(\d+) (\w+)/g, minusOne));
>// → no lemon, 1 cabbage, and 100 eggs
Код принимает строку, находит все вхождения чисел, за которыми идёт слово, и возвращает строчку, где каждое число уменьшено на единицу.
Группа >(\d+)
попадает в аргумент >amount
, а >(\w+)
– в >unit
. Функция преобразовывает >amount
в число – и это всегда срабатывает, потому что наш шаблон как раз >\d+
. И затем вносит изменения в слово, на случай, если остался всего один предмет или ни одного.
Несложно при помощи >replace
написать функцию, убирающую все комментарии из кода JavaScript. Вот первая попытка:
>function stripComments(code) {
> return code.replace(/\/\/.*|\/\*[^]*\*\//g, "");
>}
>console.log(stripComments("1 + /* 2 */3"));
>// → 1 + 3
>console.log(stripComments("x = 10;// ten!"));
>// → x = 10;
>console.log(stripComments("1 /* a */+/* b */ 1"));
>// → 1 1
Часть перед оператором «или» совпадает с двумя слэшами, за которыми идёт любое количество символов, кроме символов перевода строки. Часть, убирающая многострочные комментарии, более сложна. Мы используем , т. е. любой символ, не являющийся пустым, в качестве способа найти любой символ. Мы не можем использовать точку, потому что блочные комментарии продолжаются и на новой строке, а символ перевода строки не совпадает с точкой.
Но вывод предыдущего примера неправильный. Почему?
Часть сначала попытается захватить столько символов, сколько может. Если из-за этого следующая часть регулярки не найдёт себе совпадения, произойдёт откат на один символ и попробует снова. В примере, алгоритм пытается захватить всю строку, и затем откатывается. Откатившись на четыре символа назад, он найдёт в строчке >/
— а это не то, чего мы добивались. Мы-то хотели захватить только один комментарий, а не пройти до конца строки и найти последний комментарий.