JavaScript заменить / регулярное выражение

114

Учитывая эту функцию:

function Repeater(template) {

    var repeater = {

        markup: template,

        replace: function(pattern, value) {
            this.markup = this.markup.replace(pattern, value);
        }

    };

    return repeater;

};

Как сделать this.markup.replace()глобальную замену? Вот в чем проблема. Если я использую это так:

alert(new Repeater("$TEST_ONE $TEST_ONE").replace("$TEST_ONE", "foobar").markup);

Значение предупреждения - «foobar $ TEST_ONE».

Если я изменюсь Repeaterна следующее, то в Chrome ничего не будет заменено:

function Repeater(template) {

    var repeater = {

        markup: template,

        replace: function(pattern, value) {
            this.markup = this.markup.replace(new RegExp(pattern, "gm"), value);
        }

    };

    return repeater;

};

... и предупреждение есть $TEST_ONE $TEST_ONE.

ядро
источник

Ответы:

147

Вам нужно дважды экранировать любые символы RegExp (один раз для косой черты в строке и один раз для регулярного выражения):

  "$TESTONE $TESTONE".replace( new RegExp("\\$TESTONE","gm"),"foo")

В противном случае он ищет конец строки и «ТЕСТОН» (который никогда не находит).

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

Seth
источник
Но replace () получает регулярное выражение как переменную.
core
8
@Chris - Я не думаю, что имеет значение, используете ли вы /pattern/или new RegExp("pattern").
harto
@seth, Ваш ответ работает, но не дает решения кода из OP. Как мне вызвать код OP?
Black
82

С точки зрения интерпретации паттернов нет никакой разницы между следующими формами:

  • /pattern/
  • new RegExp("pattern")

Если вы хотите заменить буквальную строку с помощью этого replaceметода, я думаю, вы можете просто передать строку вместо регулярного выражения в replace.

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

function reEscape(s) {
    return s.replace(/([.*+?^$|(){}\[\]])/mg, "\\$1");
}

// ...

var re = new RegExp(reEscape(pattern), "mg");
this.markup = this.markup.replace(re, value);
Harto
источник
12
Раньше не знал, что / pattern / совпадает с новым RegExp ("шаблон"). Действительно помогло!
Ник Сумейко
1
Есть ли причина не использовать белый список вместо черного? например: s.replace (/ (\ W) / g, '\\ $ 1')
greg.kindel
1
Первая из перечисленных форм лучше. Рекомендуется избегать использования нового ключевого слова.
Druska
2
Неверно сказать, что литерал регулярного выражения (/ regex /) совпадает с RegExp («регулярное выражение»). В литерале регулярного выражения обратная косая черта ('\') не обязательно должна быть экранирована ('\\'), чтобы она была частью регулярного выражения. Кроме того, литерал регулярного выражения может быть скомпилирован при анализе сценария, а не при каждом выполнении функции. Чтобы соответствовать обратному солидусу, вы можете написать / \\ / или RexExp ("\\\\").
Джон
32

Ваш шаблон регулярного выражения должен иметь модификатор g:

var pattern = /[somepattern]+/g;

обратите внимание на букву g в конце. он сообщает заменителю выполнить глобальную замену.

Также вам не нужно использовать объект RegExp, вы можете создать свой шаблон, как указано выше. Пример шаблона:

var pattern = /[0-9a-zA-Z]+/g;

шаблон всегда окружен символом / с обеих сторон - с модификаторами после последнего /, причем модификатор g является глобальным.

РЕДАКТИРОВАТЬ: Почему это важно, если шаблон является переменной? В вашем случае это будет работать так (обратите внимание, что шаблон все еще является переменной):

var pattern = /[0-9a-zA-Z]+/g;
repeater.replace(pattern, "1234abc");

Но вам нужно будет изменить функцию замены на это:

this.markup = this.markup.replace(pattern, value);
Darko Z
источник