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

时间:2013-03-24 21:19:55

标签: javascript node.js regex string replace

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

然而,这不会产生“我有一只狗,一只山羊和一只猫”,而是产生“我有一只猫,一只猫和一只猫”。是否可以在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".

26 个答案:

答案 0 :(得分:345)

特定解决方案

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

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 example

概括

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

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

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

fiddle with dynamic regex

使其可重复使用

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

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

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

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

fiddle with function

要确保Object.keys在旧浏览器中有效,请添加填充,例如来自MDNEs5

答案 1 :(得分: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
}

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

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

答案 2 :(得分:7)

作为回答:

<块引用>

寻找最新的答案

如果您在当前示例中使用“单词”,您可以使用非捕获组扩展 Ben McCormick 的答案并在左侧和右侧添加单词边界 def count_matches(a, b): return sum(x == y for x, y in zip(a, b)) 以防止部分匹配。

\b
  • \b(?:cathy|cat|catch)\b 防止部分匹配的单词边界
  • \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);

答案 3 :(得分:4)

这对我有用:

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"

答案 4 :(得分:3)

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

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数组。

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

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

在现代JavaScript中: -

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

答案 5 :(得分:2)

This solution 可以只替换整个词 - 例如,在搜索“cat”时不会找到“catch”、“ducat”或“locator” .这可以通过对正则表达式中每个单词前后的单词字符使用负后视 (?<!\w) 和负前瞻 (?!\w) 来完成:

(?<!\w)(cathy|cat|ducat|locator|catch)(?!\w)

JSFiddle 演示:http://jsfiddle.net/mfkv9r8g/1/

答案 6 :(得分:2)

用户常规函数定义要替换的模式,然后使用replace函数来处理输入字符串,

var i = new RegExp('"{','g'),
    j = new RegExp('}"','g'),
    k = data.replace(i,'{').replace(j,'}');

答案 7 :(得分:1)

以防万一有人想知道为什么原始海报的解决方案无效:

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."

答案 8 :(得分:1)

/\b(cathy|cat|catch)\b/gi

“运行代码片段”以查看以下结果:

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

console.log(str);

答案 9 :(得分:1)

注意!

如果您使用动态提供的映射,这里的任何解决方案都不够!

在这种情况下,有两种方法可以解决这个问题,(1) 使用 split-join 技术,(2) 使用带有特殊字符转义技术的 Regex。

  1. 这是一种拆分连接技术,比另一种快得多(至少快 50%):

var str = "I have {abc} a c|at, a d(og, and a g[oat] {1} {7} {11."
var mapObj = {
   'c|at': "d(og",
   'd(og': "g[oat",
   'g[oat]': "c|at",
};
var entries = Object.entries(mapObj);
console.log(
  entries
    .reduce(
      // Replace all the occurrences of the keys in the text into an index placholder using split-join
      (_str, [key], i) => _str.split(key).join(`{${i}}`), 
      // Manipulate all exisitng index placeholder -like formats, in order to prevent confusion
      str.replace(/\{(?=\d+\})/g, '{-')
    )
    // Replace all index placeholders to the desired replacement values
    .replace(/\{(\d+)\}/g, (_,i) => entries[i][1])
    // Undo the manipulation of index placeholder -like formats
    .replace(/\{-(?=\d+\})/g, '{')
);

  1. 这个是 Regex 特殊字符转义技术,也可以使用,但速度要慢得多:

var str = "I have a c|at, a d(og, and a g[oat]."
var mapObj = {
   'c|at': "d(og",
   'd(og': "g[oat",
   'g[oat]': "c|at",
};
console.log(
  str.replace(
    new RegExp(
      // Convert the object to array of keys
      Object.keys(mapObj)
        // Escape any special characters in the search key
        .map(key => key.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'))
        // Create the Regex pattern
        .join('|'), 
      // Additional flags can be used. Like `i` - case-insensitive search
      'g'
    ), 
    // For each key found, replace with the appropriate value
    match => mapObj[match]
  )
);

后者的优点是它也可以用于不区分大小写的搜索。

答案 10 :(得分:0)

试试我的解决方案。随时改进

function multiReplace(strings, regex, replaces) {
  return str.replace(regex, function(x) {
    // check with replaces key to prevent error, if false it will return original value
    return Object.keys(replaces).includes(x) ? replaces[x] : x;
  });
}
var str = "I have a Cat, a dog, and a goat.";
//(json) use value to replace the key
var replaces = {
  'Cat': 'dog',
  'dog': 'goat',
  'goat': 'cat',
}
console.log(multiReplace(str, /Cat|dog|goat/g, replaces))

答案 11 :(得分:0)

你可以试试这个。买不聪明。

var str = "I have a cat, a dog, and a goat.";
console.log(str);
str = str.replace(/cat/gi, "XXX");
console.log(str);
str = str.replace(/goat/gi, "cat");
console.log(str);
str = str.replace(/dog/gi, "goat");
console.log(str);
str = str.replace(/XXX/gi, "dog");              
console.log(str);
输出: 我有一只狗、一只山羊和一只猫。

答案 12 :(得分:0)

一种可能的解决方案是使用映射器表达式函数。

const regex = /(?:cat|dog|goat)/gmi;
const str = `I have a cat, a dog, and a goat.`;

let mapper = (key) => {
  switch (key) {
    case "cat":
      return "dog"
    case "dog":
      return "goat";
    case "goat":
      return "cat"
  }
}
let result = str.replace(regex, mapper);

console.log('Substitution result: ', result);
//Substitution result1:  I have a dog, a goat, and a cat.

答案 13 :(得分:0)

我们也可以使用 split() 和 join() 方法:

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

str=str.split("cat").map(x => {return x.split("dog").map(y => {return y.split("goat").join("cat");}).join("goat");}).join("dog");

console.log(str);

答案 14 :(得分:0)

所有解决方案都可以很好地工作,除非应用于闭包的编程语言(例如Coda,Excel,电子表格的REGEXREPLACE)。

下面的两个原始解决方案仅使用1个级联和1个正则表达式。

方法1:查找替换值

这个想法是在字符串中还没有替换值时附加它们。然后,使用单个正则表达式执行所有需要的替换:

var str = "I have a cat, a dog, and a goat.";
str = (str+"||||cat,dog,goat").replace(
   /cat(?=[\s\S]*(dog))|dog(?=[\s\S]*(goat))|goat(?=[\s\S]*(cat))|\|\|\|\|.*$/gi, "$1$2$3");
document.body.innerHTML = str;

说明:

  • cat(?=[\s\S]*(dog))意味着我们正在寻找“猫”。如果匹配,则正向查找将捕获“ dog”作为组1,否则捕获“”。
  • 与将“山羊”捕获为第2组的“狗”相同,将“猫”捕获为第3组的“山羊”相同。
  • 我们将"$1$2$3"(所有三个组的串联)替换为上述情况之一的“狗”,“猫”或“山羊”
  • 如果我们将替换项手动添加到str+"||||cat,dog,goat"之类的字符串中,则通过匹配\|\|\|\|.*$来删除它们,在这种情况下,替换项"$1$2$3"的值为空字符串“”。

方法2:查找替换对

方法1的一个问题是,一次不能超过9个替换,这是反向传播组的最大数量。 方法2声明不只是附加替换值,而是直接替换:

var str = "I have a cat, a dog, and a goat.";
str = (str+"||||,cat=>dog,dog=>goat,goat=>cat").replace(
   /(\b\w+\b)(?=[\s\S]*,\1=>([^,]*))|\|\|\|\|.*$/gi, "$2");
document.body.innerHTML = str;

说明:

  • (str+"||||,cat=>dog,dog=>goat,goat=>cat")是我们将替换映射附加到字符串末尾的方式。
  • (\b\w+\b)声明“捕获任何单词”,可以用“(cat | dog | goat)或其他任何内容代替。”
  • (?=[\s\S]*...)是一种前向查找,通常会一直到文档末尾,直到替换映射之后。
    • ,\1=>的意思是“您应该在逗号和右箭头之间找到匹配的词”
    • ([^,]*)的意思是“匹配此箭头后的所有内容,直到下一个逗号或文档的末尾为止”
  • |\|\|\|\|.*$是我们移除替换地图的方式。

答案 15 :(得分:0)

通过使用原型函数,我们可以通过将键,值和可替换文本传递给对象来轻松替换

String.prototype.replaceAll=function(obj,keydata='key'){
 const keys=keydata.split('key');
 return Object.entries(obj).reduce((a,[key,val])=> a.replace(`${keys[0]}${key}${keys[1]}`,val),this)
}

const data='hids dv sdc sd ${yathin} ${ok}'
console.log(data.replaceAll({yathin:12,ok:'hi'},'${key}'))

答案 16 :(得分:0)

您可以为此使用https://www.npmjs.com/package/union-replacer。它基本上是string.replace(regexp, ...)的对应对象,它允许一次替换执行多次替换,同时保留string.replace(...)的全部功能。

披露:我是作者。开发该库是为了支持更复杂的用户可配置替换,它解决了所有问题,例如捕获组,后向引用和回调函数替换。

尽管上述解决方案足以精确替换字符串。

答案 17 :(得分:0)

您可以使用定界符查找和替换字符串。

var obj = {
  'firstname': 'John',
  'lastname': 'Doe'
}

var text = "My firstname is {firstname} and my lastname is {lastname}"

console.log(mutliStringReplace(obj,text))

function mutliStringReplace(object, string) {
      var val = string
      var entries = Object.entries(object);
      entries.forEach((para)=> {
          var find = '{' + para[0] + '}'
          var regExp = new RegExp(find,'g')
       val = val.replace(regExp, para[1])
    })
  return val;
}

答案 18 :(得分:0)

使用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)

示例

// /////////////    1. replacing using reduce and objects

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

// replaces the key in object with its value if found in the sentence
// doesn't break if words aren't found

// Example

const arrayOfObjects = [
  { plants: 'men' },
  { smart:'dumb' },
  { peace: 'war' }
]
const sentence1 = 'plants are smart'
const result1 = arrayOfObjects.reduce((f, s) => `${f}`.replace(Object.keys(s)[0], s[Object.keys(s)[0]]), sentence1)

console.log(result1)

// result1: 
// men are dumb


// Extra: string insertion python style with an array of words and indexes

// usage

// arrayOfWords.reduce((f, s, i) => `${f}`.replace(`{${i}}`, s), sentence)

// where arrayOfWords has words you want to insert in sentence

// Example

// replaces as many words in the sentence as are defined in the arrayOfWords
// use python type {0}, {1} etc notation

// five to replace
const sentence2 = '{0} is {1} and {2} are {3} every {5}'

// but four in array? doesn't break
const words2 = ['man','dumb','plants','smart']

// what happens ?
const result2 = words2.reduce((f, s, i) => `${f}`.replace(`{${i}}`, s), sentence2)

console.log(result2)

// result2: 
// man is dumb and plants are smart every {5}

// replaces as many words as are defined in the array
// three to replace
const sentence3 = '{0} is {1} and {2}'

// but five in array
const words3 = ['man','dumb','plant','smart']

// what happens ? doesn't break
const result3 = words3.reduce((f, s, i) => `${f}`.replace(`{${i}}`, s), sentence3)

console.log(result3)

// result3: 
// man is dumb and plants

答案 19 :(得分:0)

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

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

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

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

答案 20 :(得分:0)

使用我的replace-once包,您可以执行以下操作:

const replaceOnce = require('replace-once')

var str = 'I have a cat, a dog, and a goat.'
var find = ['cat', 'dog', 'goat']
var replace = ['dog', 'goat', 'cat']
replaceOnce(str, find, replace, 'gi')
//=> 'I have a dog, a goat, and a cat.'

答案 21 :(得分:0)

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

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

将用数组项替换{0}和{1}并返回以下字符串

"this is a test string for stringInject"

或者您可以使用对象键和值替换占位符,如下所示:

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

"My username is tjcafferkey on Github" 

答案 22 :(得分:0)

<!DOCTYPE html>
<html>
<body>



<p id="demo">Mr Blue 
has a           blue house and a blue car.</p>

<button onclick="myFunction()">Try it</button>

<script>
function myFunction() {
    var str = document.getElementById("demo").innerHTML;
    var res = str.replace(/\n| |car/gi, function myFunction(x){

if(x=='\n'){return x='<br>';}
if(x==' '){return x='&nbsp';}
if(x=='car'){return x='BMW'}
else{return x;}//must need



});

    document.getElementById("demo").innerHTML = res;
}
</script>

</body>
</html>

答案 23 :(得分:0)

String.prototype.replaceSome = function() {
    var replaceWith = Array.prototype.pop.apply(arguments),
        i = 0,
        r = this,
        l = arguments.length;
    for (;i<l;i++) {
        r = r.replace(arguments[i],replaceWith);
    }
    return r;
}

/ * replaceSome字符串的方法 它需要我们想要的许多论点并取代所有 他们与我们指定的最后一个参数 2013 CopyRights保存:Max Ahmed 这是一个例子:

var string = "[hello i want to 'replace x' with eat]";
var replaced = string.replaceSome("]","[","'replace x' with","");
document.write(string + "<br>" + replaced); // returns hello i want to eat (without brackets)

* /

jsFiddle:http://jsfiddle.net/CPj89/

答案 24 :(得分:-1)

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

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        for (int i = 0; i < GridView1.HeaderRow.Cells.Count; i++)
        {
            string strHeaderRow = GridView1.HeaderRow.Cells[i].Text;
            if (strHeaderRow == "ID")
            {
                string strMktURL = "http://www.address.com";
                HyperLink hlColumns = AddHyperLink(e.Row.Cells[i], strMktURL);
            }
        }
    }
}

protected HyperLink AddHyperLink(TableCell cell, string strURL)
{
    HyperLink hl = new HyperLink();
    hl.Text = cell.Text;
    hl.Font.Underline = true;
    hl.Target = "_blank";
    hl.NavigateUrl = strURL;
    hl.Attributes.Add("style", "color:Black;");
    cell.Controls.Add(hl);
    return hl;
}

答案 25 :(得分:-1)

我在@BenMcCormicks上进行了一些扩展。他曾为常规字符串工作,但如果我逃脱了字符或通配符则不行。这就是我做的事情

str = "[curl] 6: blah blah 234433 blah blah";
mapObj = {'\\[curl] *': '', '\\d: *': ''};


function replaceAll (str, mapObj) {

    var arr = Object.keys(mapObj),
        re;

    $.each(arr, function (key, value) {
        re = new RegExp(value, "g");
        str = str.replace(re, function (matched) {
            return mapObj[value];
        });
    });

    return str;

}
replaceAll(str, mapObj)

返回&#34; blah blah 234433 blah blah&#34;

这样它将匹配mapObj中的键,而不匹配匹配的单词&#39;