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

假设我想让以下内容可重复使用:

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);
}
81251 次浏览

new RegExp(string, flags)其中 flagsg或者 i所以

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

评估为

zilla

你可以的。

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

正如其他人所说,使用 new RegExp(pattern, flags)来完成这项工作。值得注意的是,您将传递字符串文字到这个构造函数中,因此必须转义每个反斜杠。例如,如果您希望正则表达式匹配反斜杠,那么您需要说 new RegExp('\\\\'),而正则表达式文本只需要是 /\\/。取决于您打算如何使用这个函数,在没有进行足够的预处理(转义特殊字符,等等)的情况下,您应该注意不要将用户输入传递给这样的函数,否则,您的用户可能会得到一些非常意想不到的结果。

对于字符串文字,这非常容易。

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

new RegExp(string_to_replace, 'g')

这样做的问题是,字符串文字中的任何 regex 特殊字符都将以其特殊的方式表现,而不是作为普通字符。你必须反斜杠-转义它们来修复这个问题。不幸的是,没有一个内置函数可以为您完成这项工作,所以这里有一个可以使用的函数:

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

还要注意,在 replace()中使用 RegExp 时,替换字符串现在也有一个特殊字符 $。如果您想在替换文本中有一个字面 $,这也必须转义!

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

(四个 $,因为它本身就是一个替换字符串ーー啊!)

现在可以用 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 _ place 之外的所有内容

这是什么意思,您想要替换所有没有参与字符串匹配的文本?用 ^替换肯定不是这样,因为 ^表示字符串开始符号,而不是否定符。在 []字符组中,^只是一个否定。也有负面的前瞻 (?!...),但是在 JScript 中有一些问题,所以您通常应该避免它。

您可以尝试匹配“ everything up to”字符串,并使用一个函数来丢弃匹配字符串之间的任何空拉伸:

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

我认为我有一个非常好的例子来突出显示字符串中的文本(它发现不是查看 register,而是使用 register 突出显示)

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中速度最快的浏览器