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

And*_*een 183 javascript regex string replace node.js

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

然而,这不会产生"我有一只狗,一只山羊和一只猫",而是产生"我有一只猫,一只猫和一只猫".是否可以在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".
Run Code Online (Sandbox Code Playgroud)

Ben*_*ick 386

具体方案

您可以使用函数替换每个函数.

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

jsfiddle的例子

概括它

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

new RegExp(Object.keys(mapObj).join("|"),"gi"); 
Run Code Online (Sandbox Code Playgroud)

生成正则表达式.那么它看起来就像这样

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

要添加或更改任何更换,您只需编辑地图即可. 

摆弄动态正则表达式

使其可重复使用

如果你想将它作为一般模式,你可以把它拉出来像这样的函数

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

    return str.replace(re, function(matched){
        return mapObj[matched.toLowerCase()];
    });
}
Run Code Online (Sandbox Code Playgroud)

那么你就可以将str和你想要的替换映射传递给函数,它将返回转换后的字符串.

摆弄功能

要确保Object.keys在旧版浏览器中可用,请添加例如来自MDNEs5的polyfill.

  • 我喜欢这个解决方案但我不得不替换`return mapObj [matched.toLowerCase()];`只是`返回mapObj [匹配];`因为我在`mapObj`中使用区分大小写的键. (4认同)
  • 您可能想要转义正则表达式的键: `Object.keys(mapObj).map(key => key.replace(/[-\/\\^$*+?.()|[\]{} ]/g, '\\$&')).join('|')`。受到[这个答案]的启发(/sf/answers/249319801/) (4认同)
  • 我不确定是否可以使用此函数替换所有类型的字符串,因为JavaScript字符串中允许的字符与JavaScript标识符中允许的字符(例如此处使用的键)不同. (2认同)
  • 您可以使用任意字符串作为javascript属性.无所谓.你不能使用带有所有这些属性的`.`符号.括号表示法适用于任何字符串. (2认同)
  • 确实很棒。我成功地使用此解决方案(“特定”解决方案),通过使用“ map = {'。”:“,”,“,”:“。”}将英语数字表示法更改为欧洲的数字表示法(从24,973.56到24.973,56)。 `和regex`/ \。|,/ g`。 (2认同)

The*_*ird 17

作为对以下问题的回答:

寻找最新的答案

如果您在当前示例中使用“单词”,您可以使用非捕获组扩展Ben McCormick的答案,并\b在左侧和右侧添加单词边界以防止部分匹配。

\b(?:cathy|cat|catch)\b
Run Code Online (Sandbox Code Playgroud)
  • \b 防止部分匹配的单词边界
  • (?: 非捕获组
    • cathy|cat|catch 匹配其中一种选择
  • ) 关闭非捕获组
  • \b 防止部分匹配的单词边界

原始问题的示例:

评论中的示例似乎效果不佳:

let str = "I have a cat, a dog, and a goat.";
const mapObj = {
  cat: "dog",
  dog: "goat",
  goat: "cat"
};
str = str.replace(/\b(?:cat|dog|goat)\b/gi, matched => mapObj[matched]);
console.log(str);
Run Code Online (Sandbox Code Playgroud)


Iia*_*ian 8

在这种情况下,这可能无法满足您的确切需求,但我发现这是替换字符串中多个参数的有用方法,作为一般解决方案.它将替换参数的所有实例,无论它们被引用了多少次:

String.prototype.fmt = function (hash) {
        var string = this, key; for (key in hash) string = string.replace(new RegExp('\\{' + key + '\\}', 'gm'), hash[key]); return string
}
Run Code Online (Sandbox Code Playgroud)

您可以按如下方式调用它:

var person = '{title} {first} {last}'.fmt({ title: 'Agent', first: 'Jack', last: 'Bauer' });
// person = 'Agent Jack Bauer'
Run Code Online (Sandbox Code Playgroud)


Emm*_*N K 6

使用Array.prototype.reduce()

const arrayOfObjects = [
  { plants: 'men' },
  { smart:'dumb' },
  { peace: 'war' }
]
const sentence = 'plants are smart'

arrayOfObjects.reduce(
  (f, s) => `${f}`.replace(Object.keys(s)[0], s[Object.keys(s)[0]]), sentence
)

// as a reusable function
const replaceManyStr = (obj, sentence) => obj.reduce((f, s) => `${f}`.replace(Object.keys(s)[0], s[Object.keys(s)[0]]), sentence)

const result = replaceManyStr(arrayOfObjects , sentence1)
Run Code Online (Sandbox Code Playgroud)

例子

const arrayOfObjects = [
  { plants: 'men' },
  { smart:'dumb' },
  { peace: 'war' }
]
const sentence = 'plants are smart'

arrayOfObjects.reduce(
  (f, s) => `${f}`.replace(Object.keys(s)[0], s[Object.keys(s)[0]]), sentence
)

// as a reusable function
const replaceManyStr = (obj, sentence) => obj.reduce((f, s) => `${f}`.replace(Object.keys(s)[0], s[Object.keys(s)[0]]), sentence)

const result = replaceManyStr(arrayOfObjects , sentence1)
Run Code Online (Sandbox Code Playgroud)

  • 如果您希望替换所有给定的字符串,而不仅仅是第一个,请添加 g 标志:“const result1 = arrayOfObjects.reduce((f, s) => `${f}`.replace(new RegExp(Object .keys(s)[0],'g'), s[Object.keys(s)[0]]), 句子1)" (2认同)

Joã*_*ulo 5

这对我有用:

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

function replaceAll(str, map){
    for(key in map){
        str = str.replaceAll(key, map[key]);
    }
    return str;
}

//testing...
var str = "bat, ball, cat";
var map = {
    'bat' : 'foo',
    'ball' : 'boo',
    'cat' : 'bar'
};
var new = replaceAll(str, map);
//result: "foo, boo, bar"
Run Code Online (Sandbox Code Playgroud)

  • [不要扩展你不拥有的对象。](https://www.nczonline.net/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/) (9认同)

Que*_*n 2 5

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

let str = "I have a %1, a %2, and a %3";
let pets = ["dog","cat", "goat"];
Run Code Online (Sandbox Code Playgroud)

然后

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

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

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

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

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

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

在现代JavaScript中:-

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

  • 一旦我们需要最终结果“我有一个狗1,一个猫1和一个山羊1”,这对于文本“我有一个%11,一个%21和一个%31”将无法正确工作。 (2认同)