Можно ли создавать регулярные выражения JavaScript на лету с помощью строковых переменных?



скажем, я хотел сделать следующее многоразовое использование:



function replace_foo(target, replacement) {
return target.replace("string_to_replace",replacement);
}


я мог бы сделать что-то вроде этого:



function replace_foo(target, string_to_replace, replacement) {
return target.replace(string_to_replace,replacement);
}


со строковыми литералами это достаточно легко. Но что если я хочу получить немного сложнее с регулярным выражением? Например, я хочу заменить все ноstring_to_replace. Инстинктивно я бы попытался расширить вышесказанное, сделав что-то вроде:



function replace_foo(target, string_to_replace, replacement) {
return target.replace(/^string_to_replace/,replacement);
}


это, кажется, не работает. Я предполагаю, что он думает string_to_replace - это строковый литерал, а не переменная, представляющая строку. Можно ли создавать регулярные выражения JavaScript на лету с помощью строковых переменных? Что-то вроде этого было бы здорово, если вообще возможно:



function replace_foo(target, string_to_replace, replacement) {
var regex = "/^" + string_to_replace + "/";
return target.replace(regex,replacement);
}
460   6  

6 ответов:

здесь new RegExp(string, flags) здесь flags are g или i. Так что

'GODzilla'.replace( new RegExp('god', 'i'), '' )

оценивает в

zilla

со строковыми литералами это достаточно легко.

не правда! Пример только заменяет первый возникновения string_to_replace. Чаще всего вы хотите заменить все вхождения, и в этом случае вам нужно преобразовать строку в глобальную (/.../g) регулярное выражение. Вы можете сделать это из строки с помощью new RegExp конструктора:

new RegExp(string_to_replace, 'g')

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

function escapeRegExp(s) {
    return s.replace(/[-/\^$*+?.()|[\]{}]/g, '\$&')
}

обратите внимание также, что при использовании регулярного выражения в replace(), строка замены теперь имеет специальный символ тоже,$. Это также должно быть экранировано, если вы хотите иметь литерал $ в вашем тексте замены!

function escapeSubstitute(s) {
    return s.replace(/$/g, '$$$$');
}

(четыре $s, потому что то есть сама строка замены-тьфу!)

теперь вы можете реализовать глобальную замену строки с регулярным выражением:

function replace_foo(target, string_to_replace, replacement) {
    var relit= escapeRegExp(string_to_replace);
    var sub= escapeSubstitute(replacement);
    var re= new RegExp(relit, 'g');
    return target.replace(re, sub);
}

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

s.split(string_to_replace).join(replacement)

...и это все. Это общепринятая идиома.

скажем, я хочу заменить все, кроме string_to_replace

что это значит, вы хотите заменить все отрезки текста, не участвующие в матче против строки? Замена на ^ конечно, это не так, потому что ^ означает маркер начала строки, а не отрицание. ^ - это только отрицание в [] групп символов. Есть также отрицательные взгляды (?!...), но есть проблемы с этим в JScript, так что вы должны вообще избегать его.

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

var re= new RegExp('(.*)($|'+escapeRegExp(string_to_find)+')')
return target.replace(re, function(match) {
    return match[1]===''? match[2] : replacement+match[2];
});

здесь, опять же, раскол может быть проще:

var parts= target.split(string_to_match);
for (var i= parts.length; i-->0;)
    if (parts[i]!=='')
        parts[i]= replacement;
return parts.join(string_to_match);

как говорили другие, используйте new RegExp(pattern, flags) для этого. Стоит отметить, что вы будете передавать строковые литералы в этот конструктор, поэтому каждый обратный Слэш должен быть экранирован. Если, например, вы хотите, чтобы ваше регулярное выражение соответствовало обратной косой черте, вам нужно будет сказать new RegExp('\\'), тогда как литерал регулярного выражения должен быть только /\/. В зависимости от того, как вы собираетесь использовать это, вы должны быть осторожны при передаче пользовательского ввода в такую функцию без соответствующей предварительной обработки (экранирование специального характеры, etc.) Без этого, ваши пользователи могут получить очень неожиданные результаты.

Да, вы можете.

https://developer.mozilla.org/en/JavaScript/Guide/Regular_Expressions

function replace_foo(target, string_to_replace, replacement) {
   var regex = new RegExp("^" + string_to_replace);
   return target.replace(regex, replacement);
}

Я думаю, что у меня есть очень хороший пример для выделения текста в строке (он находит не глядя на регистр, но выделенный с помощью регистра)

function getHighlightedText(basicString, filterString) {

    if ((basicString === "") || (basicString === null) || (filterString === "") || (filterString === null)) return basicString;

    return basicString.replace(new RegExp(filterString.replace(/[-\/\^$*+?.()|[\]{}]/g, '\\$&'), 'gi'),
        function(match)
            {return "<mark>"+match+"</mark>"});

}

http://jsfiddle.net/cdbzL/1258/

очень простое решение этой проблемы:

function replace(target, string_to_replace, replacement) {
  return target.split(string_to_replace).join(replacement);
}

нет необходимости в регулярных выражениях вообще

Он также кажется самым быстрым в современных браузерах https://jsperf.com/replace-vs-split-join-vs-replaceall

Comments

    Ничего не найдено.