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


213

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

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

我想用多个其他单词替换字符串中的多个单词,而不替换已经替换的单词。
Anderson Green

我有一些不同的查询,如果我不知道用户要输入猫还是狗或山羊(这是随机出现的)怎么办,但是每当出现这种字时,我都需要用“动物”来代替。如何获得这种情况
Prasanna Sasne

Answers:


445

具体解决方案

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

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


4
我不确定是否可以使用此函数替换所有类型的字符串,因为JavaScript字符串中允许使用的字符与JavaScript标识符中允许使用的字符(例如此处使用的键)不同。
Anderson Green

2
您可以使用任意字符串作为javascript属性。没关系 您只是不能将.符号与所有这些属性一起使用。括号符号适用于任何字符串。
本·麦考密克

2
它确实很棒。我成功地使用了此解决方案(“特定”解决方案),使用map={'.': ',', ',': '.'}和regex 将英语数字表示法更改为欧洲的数字表示法(从24,973.56到24.973,56)/\.|,/g
Sygmoral

5
我喜欢这种解决方案,但由于在中使用了区分大小写的键,因此我不得不替换return mapObj[matched.toLowerCase()];为。return mapObj[matched];mapObj
Michal Moravcik

2
您可能需要转义正则表达式的键:Object.keys(mapObj).map(key => key.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')).join('|')。受此答案的
robsch

9

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

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'

8

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

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

有趣。您能否解释替换功能中的逻辑?
Eric Hepperle-CodeSlayer2010 '18

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"


如果字符串包含正则表达式字符,则无效。
罗默

关于“不要扩展...”:我扩展了String以比较两个字符串是否相等,不区分大小写。String未提供此功能,但是可能有一天会导致我的应用程序中断。有没有一种方法可以“子类化”或“扩展”字符串以安全地包含此类函数,还是我应该在应用程序库中简单地定义一个新的具有两个参数的函数?
David Spector

4

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


最佳答案。但是,是否有理由使用${f}代替f的累加值?
David Spector

1
如果要替换所有给定的字符串,而不仅仅是第一个,则添加g标志:“ const result1 = arrayOfObjects.reduce((f,s)=> ${f}.replace(new RegExp(Object.keys(s)[ 0],'g'),s [Object.keys(s)[0]]),句子1)“
David Spector

2

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

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

哈哈……分析得很好……竖起大拇指
Deepa MG

1

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

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

如果您不知道跳过,但不要说这是错误的答案。像这样的情况“ {{a”:1,“ b”:2}“”就是我用来替换上述方式的地方。如果其他人想要其他人有帮助,那么答案不仅仅适合您。@Carr
KARTHIKEYAN.A

再次,您只是提供了一个毫无意义的答案,您所要做的就是提问者在问题中已经可以做的,这个答案将误导人们他们可能认为是新事物并利用该RegExp物体可以解决问题
Carr

在这种情况下,您仍然遇到与问问者问题相同的问题var i = new RegExp('}','g'), j = new RegExp('{','g'), k = data.replace(i,'{').replace(j,'}');
Carr

1

使用一次替换包,您可以执行以下操作:

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

这个软件包是惊人的:)完全符合我的预期
Vishnu Prassad

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

3
在OP问“是否有可能取代与多个其他串多串在同一时间 ”。这是三个单独的步骤。
LittleBobbyTables-Au Revoir

1

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

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


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/


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>

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" 

0

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

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

上面的解决方案足以精确替换字符串。


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

返回“等等……234433等等……”

这样,它将匹配mapObj中的键,而不是匹配的单词'


// //不值钱:replaceAll(“我有一只猫,一条狗和一只山羊。”,{cat:“ dog”,dog:“ goat”,山羊:“ cat”})//产生:“我有一只猫,一只猫和一只猫。”
devon

-3

jQuery的解决方案(首先包含此文件):用多个其他字符串替换多个字符串:

var replacetext = {
    "abc": "123",
    "def": "456"
    "ghi": "789"
};

$.each(replacetext, function(txtorig, txtnew) {
    $(".eng-to-urd").each(function() {
        $(this).text($(this).text().replace(txtorig, txtnew));
    });
});

此解决方案是否需要JQuery?
安德森·格林

有问题的javascript标记,而jquery是javascript的库。
超级模特

2
@Super javascript tag added in question, and jquery is a libarary of javascript.Hmmm,该逻辑已关闭,应该是相反的方向,并且也应引起注意-来自javascript标签信息:“ 除非还包括框架/库的另一个标签,否则应该有纯JavaScript答案。
Traxo

@Anderson Green,是的,上面的脚本需要使用jQuery。
超级模特

@ Traxo,在大多数Web应用程序中,我们都使用框架(bootstrap / google资料)。jQuery包含在所有现代框架中。因此,jQuery是Web应用程序的必要项。
超级模特(
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.