如何替换 JavaScript 中所有出现的字符串?

2022-08-29 21:44:40

给定一个字符串:

s = "Test abc test test abc test test test abc test test abc";

这似乎只删除了上面字符串中第一次出现的 :abc

s = s.replace('abc', '');

如何替换所有出现的它?


答案 1

截至 2020 年 8 月:现代浏览器支持 ECMAScript 2021 语言规范定义的 String.replaceAll() 方法


对于旧版/旧版浏览器:

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}

function replaceAll(str, find, replace) {
  return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}

以下是这个答案是如何演变的:

str = str.replace(/abc/g, '');

在回应评论“如果'abc'作为变量传递会怎样?”时:

var find = 'abc';
var re = new RegExp(find, 'g');

str = str.replace(re, '');

为了回应Click Upvote的评论,您可以进一步简化它:

function replaceAll(str, find, replace) {
  return str.replace(new RegExp(find, 'g'), replace);
}

注意:正则表达式包含特殊(元)字符,因此,在上述函数中盲目传递参数而不对其进行预处理以转义这些字符是危险的。这在Mozilla Developer NetworkJavaScript Guide on Regular Expressions中有所介绍,其中提供了以下实用程序函数(自最初编写此答案以来,该函数已更改至少两次,因此请务必检查MDN站点以获取潜在的更新):find

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}

因此,为了使上述功能更安全,如果您还包括以下内容,则可以将其修改为以下内容:replaceAll()escapeRegExp

function replaceAll(str, find, replace) {
  return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}

答案 2

为了完整起见,我不得不考虑我应该使用哪种方法来做到这一点。基本上有两种方法可以做到这一点,如本页上的其他答案所建议的那样。

注意:通常,通常不建议在JavaScript中扩展内置原型。我提供 String 原型上的扩展只是为了便于说明,在内置原型上展示假设标准方法的不同实现。String


基于正则表达式的实现

String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.replace(new RegExp(search, 'g'), replacement);
};

拆分和连接(功能)实现

String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.split(search).join(replacement);
};

由于不太了解正则表达式在幕后效率方面的工作方式,我倾向于过去的拆分和加入实现,而不考虑性能。当我确实想知道哪个更有效率,以什么幅度时,我用它作为借口来找出答案。

在我的Chrome Windows 8计算机上,基于正则表达式的实现速度最快拆分和联接实现速度慢了53%。这意味着正则表达式的速度是我使用的 lorem ipsum 输入的两倍。

查看此基准测试,将这两个实现相互运行。


正如@ThomasLeduc和其他人在下面的评论中指出的那样,如果包含某些在正则表达式中保留为特殊字符的字符,则基于正则表达式的实现可能存在问题。该实现假定调用方将事先转义字符串,或者仅传递正则表达式 (MDN) 中没有表中字符的字符串。search

MDN还提供了一个实现来转义我们的字符串。如果这也被标准化为 ,那就太好了,但唉,它不存在:RegExp.escape(str)

function escapeRegExp(str) {
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
}

我们可以在实现中调用,但是,我不确定这会对性能产生多大影响(甚至可能对于不需要转义的字符串,如所有字母数字字符串)。escapeRegExpString.prototype.replaceAll