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

bul*_*ley 132 javascript regex

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

function replace_foo(target, replacement) {
   return target.replace("string_to_replace",replacement);
}
Run Code Online (Sandbox Code Playgroud)

我可能会这样做:

function replace_foo(target, string_to_replace, replacement) {
   return target.replace(string_to_replace,replacement);
}
Run Code Online (Sandbox Code Playgroud)

使用字符串文字这很容易.但是,如果我想让正则表达式变得更加棘手呢?例如,假设我想取代一切,但 string_to_replace.本能地,我会尝试通过以下方式扩展上述内容:

function replace_foo(target, string_to_replace, replacement) {
   return target.replace(/^string_to_replace/,replacement);
}
Run Code Online (Sandbox Code Playgroud)

这似乎不起作用.我的猜测是它认为string_to_replace是字符串文字,而不是表示字符串的变量.是否可以使用字符串变量动态创建JavaScript正则表达式?如果可能的话,这样的事情会很棒:

function replace_foo(target, string_to_replace, replacement) {
   var regex = "/^" + string_to_replace + "/";
   return target.replace(regex,replacement);
}
Run Code Online (Sandbox Code Playgroud)

med*_*iev 206

还有new RegExp(string, flags)哪里flagsgi.所以

'GODzilla'.replace( new RegExp('god', 'i'), '' )
Run Code Online (Sandbox Code Playgroud)

评估为

zilla
Run Code Online (Sandbox Code Playgroud)

  • 并且在使用此表单时省略`/`正则表达式分隔符. (29认同)

bob*_*nce 111

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

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

new RegExp(string_to_replace, 'g')
Run Code Online (Sandbox Code Playgroud)

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

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

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

function escapeSubstitute(s) {
    return s.replace(/\$/g, '$$$$');
}
Run Code Online (Sandbox Code Playgroud)

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

现在,您可以使用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);
}
Run Code Online (Sandbox Code Playgroud)

太痛苦了.幸运的是,如果你想做的只是一个直接的字符串替换没有正则表达式的其他部分,有一个更快的方法:

s.split(string_to_replace).join(replacement)
Run Code Online (Sandbox Code Playgroud)

...就这样.这是一个普遍理解的习语.

说我想替换除了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];
});
Run Code Online (Sandbox Code Playgroud)

在这里,分裂可能更简单:

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);
Run Code Online (Sandbox Code Playgroud)


小智 10

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

  • 这个答案虽然不是最详细的,但确实提到了一个**关键的**细节,我只是坚持了一个小时:逃避任何特殊的序列.例如,我正在搜索以某个术语开头的单词,所以我需要的正则表达式是`/\b [term]\B /`,但是在构造它时我需要调用`new RegExp("\\ b"+ term +"\\ B")`.小而重要的差异,并且很难发现因为直接使用它作为正则表达式**确实**按预期工作. (3认同)

Kri*_*nck 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);
}
Run Code Online (Sandbox Code Playgroud)