如何替换 JavaScript 中所有出现的字符串?
给定一个字符串:
string = "Test abc test test abc test test test abc test test abc";
这似乎只能删除上面字符串中第一次出现的
abc
:
string = string.replace('abc', '');
如何替换 所有 出现的字符串?
截至 2020 年 8 月:
现代浏览器支持
ECMAScript 2021 语言规范定义的
String.replaceAll()
方法
。
对于较旧/旧版浏览器:
function escapeRegExp(str) {
return str.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);
}
注意
:正则表达式包含特殊(元)字符,因此,如果不预先处理以转义这些字符,就盲目地在上述
find
函数中传递参数是危险的。
Mozilla 开发者网络
的
JavaScript 正则表达式指南
中介绍了此内容,其中介绍了以下实用函数(自最初编写此答案以来,该函数至少已更改两次,因此请务必检查 MDN 站点以获取可能的更新):
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);
}
为了完整起见,我开始思考应该使用哪种方法来执行此操作。根据本页上其他答案的建议,基本上有两种方法可以做到这一点。
注意:
通常,通常不建议扩展 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 和其他人在下面的评论中指出的那样,如果
search
包含某些保留为
正则表达式中的特殊字符
的字符,则基于正则表达式的实现可能会出现问题。该实现假定调用者将事先对字符串进行转义,或者仅传递不包含
正则表达式
(MDN) 中表中字符的字符串。
MDN 还提供了一种转义字符串的实现。如果这也被标准化为
RegExp.escape(str)
,那就太好了,但可惜的是,它不存在:
function escapeRegExp(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
}
我们可以在
String.prototype.replaceAll
实现中调用
escapeRegExp
,但是,我不确定这会对性能产生多大影响(甚至可能对不需要转义的字符串产生影响,例如所有字母数字字符串)。
在大多数流行浏览器的最新版本中,您可以使用
replaceAll
如下所示:
let result = "1 abc 2 abc 3".replaceAll("abc", "xyz");
// `result` is "1 xyz 2 xyz 3"
但请先检查 我可以使用吗 或其他兼容性表,以确保您所针对的浏览器已首先添加对它的支持。
对于 Node.js 和与旧版/非当前浏览器的兼容性:
注意:请勿在性能关键代码中使用以下解决方案。
作为简单文字字符串的正则表达式的替代,您可以使用
str = "Test abc test test abc test...".split("abc").join("");
一般模式是
str.split(search).join(replacement)
在某些情况下,这比使用
replaceAll
和正则表达式更快,但在现代浏览器中似乎不再如此。
基准测试: https://jsben.ch/TZYzj
结论:
如果您有一个性能至关重要的用例(例如,处理数百个字符串),请使用正则表达式方法。但对于大多数典型用例,这非常值得,因为不必担心特殊字符。