使用字符串变量动态创建RegExps

时间:2010-12-06 22:26:49

标签: javascript regex

说我想让以下可重复使用:

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);
}

6 个答案:

答案 0 :(得分:196)

new RegExp(string, flags) flagsgi。所以

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

评估为

zilla

答案 1 :(得分:106)

  

使用字符串文字这很容易。

不是真的!该示例仅替换string_to_replace第一个出现。更常见的是,您希望替换所有匹配项,在这种情况下,您必须将字符串转换为全局(/.../g)RegExp。您可以使用new RegExp构造函数从字符串执行此操作:

new RegExp(string_to_replace, 'g')

这个问题是字符串文字中的任何正则表达式特殊字符都会以其特殊方式运行,而不是普通字符。你必须反斜杠 - 逃避他们来解决这个问题。不幸的是,没有内置功能可以为你做这个,所以这是你可以使用的:

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

另请注意,当您在replace()中使用RegExp时,替换字符串现在也具有特殊字符$。如果您想在替换文字中添加文字$,也必须对其进行转义!

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

(四个$因为它本身就是一个替代字符串-agh!)

现在您可以使用RegExp实现全局字符串替换:

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);

答案 2 :(得分:10)

正如其他人所说,使用new RegExp(pattern, flags)来做到这一点。值得注意的是,您将把字符串文字传递给此构造函数,因此必须对每个反斜杠进行转义。例如,如果您希望正则表达式匹配反斜杠,则需要说new RegExp('\\\\'),而正则表达式文字只需要/\\/。根据您打算如何使用它,您应该小心将用户输入传递给这样的函数而没有足够的预处理(转义特殊字符等)。如果没有这个,您的用户可能会得到一些非常意外的结果。

答案 3 :(得分:5)

是的,你可以。

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);
}

答案 4 :(得分:0)

我认为我在字符串中突出显示文本有很好的例子(它找不到寄存器但是使用寄存器突出显示)

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/

答案 5 :(得分:0)

一个非常简单的解决方案就是:

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

根本不需要正则表达式

它似乎也是现代浏览器https://jsperf.com/replace-vs-split-join-vs-replaceall

上最快的