用多个其他字符串替换多个字符串

我正在尝试用多个其他单词替换字符串中的多个单词。字符串是“我有一只猫,一只狗和一只山羊”。

但是,它不会产生“我有一只狗,一只山羊和一只猫”,而是会产生“我有一只猫,一只猫和一只猫”。在JavaScript中是否可以同时用多个其他字符串替换多个字符串,以便产生正确的结果?

var str = "I have a cat, a dog, and a goat.";
str = str.replace(/cat/gi, "dog");
str = str.replace(/dog/gi, "goat");
str = str.replace(/goat/gi, "cat");

//this produces "I have a cat, a cat, and a cat"
//but I wanted to produce the string "I have a dog, a goat, and a cat".
飞云2020/03/23 15:39:38

我写了这个npm包stringinject https://www.npmjs.com/package/stringinject,它允许您执行以下操作

var string = stringInject("this is a {0} string for {1}", ["test", "stringInject"]);

which will replace the {0} and {1} with the array items and return the following string

"this is a test string for stringInject"

or you could replace placeholders with object keys and values like so:

var str = stringInject("My username is {username} on {platform}", { username: "tjcafferkey", platform: "GitHub" });

"My username is tjcafferkey on Github" 
小宇宙2020/03/23 15:39:38

以防万一有人想知道为什么原始海报的解决方案不起作用:

var str = "I have a cat, a dog, and a goat.";

str = str.replace(/cat/gi, "dog");
// now str = "I have a dog, a dog, and a goat."

str = str.replace(/dog/gi, "goat");
// now str = "I have a goat, a goat, and a goat."

str = str.replace(/goat/gi, "cat");
// now str = "I have a cat, a cat, and a cat."
宝儿理查德2020/03/23 15:39:38

具体解决方案

您可以使用一个函数替换每个函数。

var str = "I have a cat, a dog, and a goat.";
var mapObj = {
   cat:"dog",
   dog:"goat",
   goat:"cat"
};
str = str.replace(/cat|dog|goat/gi, function(matched){
  return mapObj[matched];
});

jsfiddle示例

概括它

如果您要动态维护正则表达式并仅将将来的交换添加到地图,则可以执行此操作

new RegExp(Object.keys(mapObj).join("|"),"gi"); 

生成正则表达式。所以看起来像这样

var mapObj = {cat:"dog",dog:"goat",goat:"cat"};

var re = new RegExp(Object.keys(mapObj).join("|"),"gi");
str = str.replace(re, function(matched){
  return mapObj[matched];
});

要添加或更改其他替换,您只需编辑地图即可。 

摆弄动态正则表达式

使其可重用

如果您希望这是一种通用模式,则可以将其拉出类似这样的功能

function replaceAll(str,mapObj){
    var re = new RegExp(Object.keys(mapObj).join("|"),"gi");

    return str.replace(re, function(matched){
        return mapObj[matched.toLowerCase()];
    });
}

因此,您只需将str和所需替换的映射传递给函数,它将返回转换后的字符串。

摆弄功能

为了确保Object.keys在较旧的浏览器中可以正常运行,请添加一个polyfill例如从MDNEs5

Itachi猿小小2020/03/23 15:39:38

使用编号的项目以防止再次更换。例如

let str = "I have a %1, a %2, and a %3";
let pets = ["dog","cat", "goat"];

然后

str.replace(/%(\d+)/g, (_, n) => pets[+n-1])

工作原理:-%\ d +查找%之后的数字。方括号捕获数字。

该数字(作为字符串)是lambda函数的第二个参数n。

+ n-1将字符串转换为数字,然后减去1以索引pets数组。

然后将%number替换为数组索引处的字符串。

/ g导致用每个数字重复调用lambda函数,然后将其替换为数组中的字符串。

在现代JavaScript中:-

replace_n=(str,...ns)=>str.replace(/%(\d+)/g,(_,n)=>ns[n-1])