325

I'm trying to replace multiple words in a string with multiple other words. The string is "I have a cat, a dog, and a goat."

However, this does not produce "I have a dog, a goat, and a cat", but instead it produces "I have a cat, a cat, and a cat". Is it possible to replace multiple strings with multiple other strings at the same time in JavaScript, so that the correct result will be produced?

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".
KARTHIKEYAN.A
  • 18,210
  • 6
  • 124
  • 133
Anderson Green
  • 30,230
  • 67
  • 195
  • 328
  • I want to replace multiple words in a string with multiple other words, without replacing words that have already been replaced. – Anderson Green Mar 24 '13 at 21:21
  • i've some different query, what if i dnt know user is going to enter cat or dog or goat(this is randomly coming) but whenever this kinda word will come i need to replace with let's say 'animal'. how to get this scenario – Prasanna Nov 05 '18 at 08:06
  • The top-voted answer to this question seems to be incorrect: it sometimes replaces the strings [in the wrong order](http://jsfiddle.net/xfkj2r3s/). – Anderson Green Apr 30 '21 at 17:47
  • 1
    @AndersonGreen in your example why `cat` should not match the `cat` part of `catch`? You should precise the match criteria. – Guerric P Apr 30 '21 at 18:32
  • @GuerricP I need to match and replace every string when possible. In this case, the word "catch" doesn't get matched at all, since the word "cat" appears first in the regex. – Anderson Green Apr 30 '21 at 19:01
  • In this case just surround every word with `\b` in the regex: http://jsfiddle.net/rkc52a0u/ – Guerric P Apr 30 '21 at 19:03
  • 321 votes in total  :p – Petəíŕd The Linux Wizard May 28 '23 at 17:25

28 Answers28

620

Specific Solution

You can use a function to replace each one.

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

Generalizing it

If you want to dynamically maintain the regex and just add future exchanges to the map, you can do this

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

to generate the regex. So then it would look like this

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

And to add or change any more replacements you could just edit the map. 

fiddle with dynamic regex

Making it Reusable

If you want this to be a general pattern you could pull this out to a function like this

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

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

So then you could just pass the str and a map of the replacements you want to the function and it would return the transformed string.

fiddle with function

To ensure Object.keys works in older browsers, add a polyfill eg from MDN or Es5.

SirDerpington
  • 11,260
  • 4
  • 49
  • 55
Ben McCormick
  • 25,260
  • 12
  • 52
  • 71
  • 4
    I'm not sure if I could use this function to replace all types of strings, since the characters that are allowed in JavaScript strings are not the same as the characters that are allowed in JavaScript identifiers (such as the keys that are used here). – Anderson Green May 23 '13 at 22:22
  • 3
    you can use an arbitrary string in as a javascript property. Shouldn't matter. You just can't use the `.` notation with all such properties. Brackets notation works with any string. – Ben McCormick May 23 '13 at 23:18
  • 2
    It indeed works great. I am succesfully using this solution (the 'specific' one) to change English number notations into European ones (24,973.56 to 24.973,56), using `map={'.': ',', ',': '.'}` and regex `/\.|,/g`. – Sygmoral Aug 28 '13 at 08:51
  • Just wanted to add the functionality to replace with empty strings: return mapObj[matched] ? mapObj[matched] : ''; – Robert Brisita Oct 24 '13 at 22:24
  • i think there's a bug related to it since it only does the replacement once. check out this fiddle. http://jsfiddle.net/L6LB2/33/ – bonbon.langes Nov 11 '13 at 15:43
  • @bonbon.langes it works for multiple selections, it does fail for uppercase words though. Fixed here: http://jsfiddle.net/L6LB2/35/ – Ben McCormick Nov 11 '13 at 18:26
  • 8
    I love this solution but I had to replace `return mapObj[matched.toLowerCase()];` to just `return mapObj[matched];` since I use case sensitive keys in `mapObj`. – Michal Moravcik Nov 21 '14 at 13:02
  • Smart! I moved out the regexp definition cause in my case the map it doesn't change. Here is my implementation: [fiddle](https://jsfiddle.net/2g5s1bc5/) – pliski Apr 12 '15 at 23:28
  • Oh that's awesome, using an object to solve the problems makes everything easier, I wasn't expecting for that +1 – Kyle Oct 27 '15 at 11:47
  • according to jsperf this solution is a lot slower than chaining .replace() calls – MiniScalope May 26 '17 at 21:26
  • 1
    @MiniScalope Chaining replace calls can cause bugs if you're swapping 2 words, since if you made all `dogs` `cats` then made all `cats` `dogs`, every word that was originally `dogs` or `cats` would end up as `dogs` – Ben McCormick Jul 27 '17 at 16:48
  • 1
    Not working if the input is `dog`,`doge`. Only the first one in the RegExp will match. That is to say `dog|doge` will match `dog` while `doge|dog` will fail `dog` – 牛さん Dec 15 '18 at 07:30
  • this is a BUG: return mapObj[matched.toLowerCase()]; >> .toLowerCase() not required – klodoma Mar 05 '19 at 12:49
  • 8
    You may want to escape the keys for the regular expression: `Object.keys(mapObj).map(key => key.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')).join('|')`. Inspired by [this answer](https://stackoverflow.com/a/3561711/57091) – robsch Jul 16 '19 at 12:20
  • This solution won't always work if the replaced strings overlap: see [here](http://jsfiddle.net/xfkj2r3s/), for example. – Anderson Green Apr 30 '21 at 17:22
  • @AndersonGreen What do you expect this to do? If you're looking to replace "strings" in general, your question applied to your jsfiddle is ambiguous: It's not clear if `cathy` should turn into `cat` or `catchthy`. Do you want to replace the _longest_ string matching, out of all matches you have? Or perhaps precise matches of words, delimited by spaces, comma etc.? – Nearoo May 06 '21 at 15:08
  • 1
    @AndersonGreen when you have substrings you just need to be a bit more careful about the ordering. For instance I think this will likely produce the result you're expecting: `str = str.replace(/cathy|catch|cat/gi, function(matched){...})` – Ben McCormick May 06 '21 at 19:20
45

As an answer to:

looking for an up-to-date answer

If you are using "words" as in your current example, you might extend the answer of Ben McCormick using a non capture group and add word boundaries \b at the left and at the right to prevent partial matches.

\b(?:cathy|cat|catch)\b
  • \b A word boundary to prevent a partial match
  • (?: Non capture group
    • cathy|cat|catch match one of the alternatives
  • ) Close non capture group
  • \b A word boundary to prevent a partial match

Example for the original question:

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

Example for the example in the comments that not seems to be working well:

let str = "I have a cat, a catch, and a cathy.";
const mapObj = {
  cathy: "cat",
  cat: "catch",
  catch: "cathy"

};
str = str.replace(/\b(?:cathy|cat|catch)\b/gi, matched => mapObj[matched]);
console.log(str);
The fourth bird
  • 154,723
  • 16
  • 55
  • 70
20

Use numbered items to prevent replacing again. eg

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

then

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

How it works:- %\d+ finds the numbers which come after a %. The brackets capture the number.

This number (as a string) is the 2nd parameter, n, to the lambda function.

The +n-1 converts the string to the number then 1 is subtracted to index the pets array.

The %number is then replaced with the string at the array index.

The /g causes the lambda function to be called repeatedly with each number which is then replaced with a string from the array.

In modern JavaScript:-

replace_n=(str,...ns)=>str.replace(/%(\d+)/g,(_,n)=>ns[n-1])
Quentin 2
  • 2,156
  • 1
  • 10
  • 8
13

This may not meet your exact need in this instance, but I've found this a useful way to replace multiple parameters in strings, as a general solution. It will replace all instances of the parameters, no matter how many times they are referenced:

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

You would invoke it as follows:

var person = '{title} {first} {last}'.fmt({ title: 'Agent', first: 'Jack', last: 'Bauer' });
// person = 'Agent Jack Bauer'
Iian
  • 195
  • 9
  • 1
    This works only if your keys not include any special regex characters. Otherwise, it will return error or worse, an unexpected behavior. E.g: `'abc'.fmt({'a(b':1})` – Slavik Meltser Apr 30 '21 at 16:39
10

using Array.prototype.reduce():

UPDATED (much better) answer (using object): This function will replace all occurrences and is case insensitive

/**
 * Replaces all occurrences of words in a sentence with new words.
 * @function
 * @param {string} sentence - The sentence to modify.
 * @param {Object} wordsToReplace - An object containing words to be replaced as the keys and their replacements as the values.
 * @returns {string} - The modified sentence.
 */
function replaceAll(sentence, wordsToReplace) {
  return Object.keys(wordsToReplace).reduce(
    (f, s, i) =>
      `${f}`.replace(new RegExp(s, 'ig'), wordsToReplace[s]),
      sentence
  )
}

const americanEnglish = 'I popped the trunk of the car in a hurry and in a hurry I popped the trunk of the car'
const wordsToReplace = {
  'popped': 'opened',
  'trunk': 'boot',
  'car': 'vehicle',
  'hurry': 'rush'
}

const britishEnglish = replaceAll(americanEnglish, wordsToReplace) 
console.log(britishEnglish)
// I opened the boot of the vehicle in a rush and in a rush I opened the boot of the vehicle

ORIGINAL answer (using array of objects):

    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)

Example

// /////////////    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
Emmanuel N K
  • 8,710
  • 1
  • 31
  • 37
  • Best answer. But is there a reason to use `${f}` instead of f for the accumulating value? – David Spector Sep 06 '19 at 18:27
  • 3
    If you want ALL of the given strings to be replaced, not just the first, add the g flag: "const result1 = arrayOfObjects.reduce((f, s) => `${f}`.replace(new RegExp(Object.keys(s)[0],'g'), s[Object.keys(s)[0]]), sentence1)" – David Spector Sep 06 '19 at 18:55
  • Note @David Spector's comment for replacing ALL of the given strings should be '$(f)' not $(f) – gordon613 Nov 06 '22 at 16:18
  • And to add to @David Spector's comment, if you want it to replace ALL of the given strings *and* be case insensitive, then use 'ig' not 'g' – gordon613 Nov 06 '22 at 16:19
5

This worked for me:

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"
João Paulo
  • 6,300
  • 4
  • 51
  • 80
  • 9
    [Don't extend objects you don't own.](https://www.nczonline.net/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/) – fregante May 29 '17 at 13:30
  • Doesn't work if the string contains regex characters. – Roemer Jun 18 '19 at 18:34
  • About "don't extend...": I extended my String to compare two strings for equality, case-insensitive. This functionality is not provided by String, but it might be someday, which could cause my apps to break. Is there a way to "subclass" or "extend" String to include such a function safely, or should I simply define a new two-argument function as part of my app library? – David Spector Sep 06 '19 at 17:58
4

With my replace-once package, you could do the following:

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.'
Kodie Grantham
  • 1,963
  • 2
  • 17
  • 27
4

NOTE!

If you are using dynamically provided mapping, NONE of the solutions here are sufficient enough!

In this case, there are two ways to solve this problem, (1) using split-join technique, (2) using Regex with special character escaping technique.

  1. This one is a split-join technique, which is much more faster than the other one (at least 50% faster):

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. This one, is the Regex special character escaping technique, which also works, but much slower:

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

The advantage of the latter, is that it can also work with case-insensitive search.

Slavik Meltser
  • 9,712
  • 3
  • 47
  • 48
  • What is "dynamically provided mapping?" – Anderson Green Apr 30 '21 at 17:16
  • "dynamically provided mapping" is an unknown content of keys and value and in unknown quantity during the development process. Such information can be known mostly during runtime. E.g. user input. – Slavik Meltser Apr 30 '21 at 18:22
  • 1
    This mostly works, except in some cases where [the keys overlap](https://jsfiddle.net/fjxevbh0/). It might work better if the keys in the regex were sorted by length (from longest to shortest). – Anderson Green May 03 '21 at 16:21
  • @AndersonGreen True, you can sort it by size. But it really depends on your use case. Some may prefer to look for shortest first, though. In your case is can be easily solved with `Object.keys(mapObj).sort((a,b) => b.length - a.length)` – Slavik Meltser May 09 '21 at 15:53
  • Hey, nice solution! Is it possible to adapt to tags? example: (find: "

    – Sophie Mar 17 '22 at 23:14
  • @Sophie sure, everything is possible, it’s programming :) You can try and support also regex as a replacer in the `mapObj` - which may help you achieve your goal. – Slavik Meltser Mar 26 '22 at 22:27
3

Just in case someone is wondering why the original poster's solution is not working:

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."
jack
  • 1,391
  • 6
  • 21
3

You can find and replace string using delimiters.

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

var text = "Hello {firstname}, Your firstname is {firstname} and 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;
}
Naresh Kumar
  • 871
  • 7
  • 8
3

one possible solution could be by using the mapper expression function.

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.
Taimoor Qureshi
  • 620
  • 4
  • 14
2

This solution can be adapted to only replace whole words - so for example, "catch", "ducat" or "locator" wouldn't be found when searching for "cat". This can be done by using negative lookbehind (?<!\w) and negative lookahead (?!\w) on word characters before and after each word in the regular expression:

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

JSFiddle demo: http://jsfiddle.net/mfkv9r8g/1/

Steve Chambers
  • 37,270
  • 24
  • 156
  • 208
  • This won't work in cases where the input string contains special regex characters: see [here](http://jsfiddle.net/z8x6ucqr/), for example. You also need to escape these characters. – Anderson Green May 06 '21 at 18:54
  • Yes, you'd need to escape special characters in the regex if they need to be replaced - like [this](http://jsfiddle.net/50q12tsa/) if the objective is to replace `cat)` - not sure I understand why this is an issue? – Steve Chambers May 07 '21 at 08:10
2

Try my solution. feel free to improve

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

const str = 'Thanks for contributing an answer to Stack Overflow!'
    const substr = ['for', 'to']

    function boldString(str, substr) {
        let boldStr
        boldStr = str
        substr.map(e => {
                const strRegExp = new RegExp(e, 'g');
                boldStr= boldStr.replace(strRegExp, `<strong>${e}</strong>`);
            }
        )
        return boldStr
}
1

user regular function to define the pattern to replace and then use replace function to work on input string,

var i = new RegExp('"{','g'),
    j = new RegExp('}"','g'),
    k = data.replace(i,'{').replace(j,'}');
KARTHIKEYAN.A
  • 18,210
  • 6
  • 124
  • 133
  • If you not aware skip, but don't say it is the wrong answer. My case "{"a":1,"b":2}" like that is there I used to replace the above way. If it helps others if they want for other the answer is not for you only. @Carr – KARTHIKEYAN.A Oct 26 '19 at 05:15
  • Again, you just provided a meaningless answer, what you do is the asker already can do in the question, this answer will mislead people that they may think new and utilize the `RegExp` object could solve the problem – Carr Oct 27 '19 at 16:27
  • In this case, you still have the same problem as asker's question when you do `var i = new RegExp('}','g'), j = new RegExp('{','g'), k = data.replace(i,'{').replace(j,'}');` – Carr Oct 27 '19 at 16:28
1
/\b(cathy|cat|catch)\b/gi

"Run code snippet" to see the results below:

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);
Leftium
  • 16,497
  • 6
  • 64
  • 99
  • Instead of adding word boundaries, you could also sort the strings in the regex by length, so that the longest strings would be matched first. – Anderson Green May 02 '21 at 15:41
  • I think your answer is the way to go, but if I were you, I will provide a more general way to do that with `/\w+/g` as pattern, and with a function that returns the match when the property doesn't exist in your object. Also, instead of a *standard* object, I think a Map is more appropriate: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map . To finish, the help of `toLowerCase()` or `toUpperCase()` can be usefull. – Casimir et Hippolyte May 02 '21 at 18:29
  • 1
    @AndersonGreen Sorting the strings will give slightly different results. For example, "cats" will be changed to "catchs." Word boundaries will leave "cats" intact. It depends on the behavior desired. – Leftium May 02 '21 at 22:42
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 method for strings it takes as ,much arguments as we want and replaces all of them with the last argument we specified 2013 CopyRights saved for: Max Ahmed this is an example:

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>
Jalaluddin Rumi
  • 71
  • 1
  • 1
  • 8
0

I wrote this npm package stringinject https://www.npmjs.com/package/stringinject which allows you to do the following

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" 
codebytom
  • 418
  • 4
  • 12
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."
Sanogoals
  • 31
  • 9
0

You can use https://www.npmjs.com/package/union-replacer for this purpose. It is basically a string.replace(regexp, ...) counterpart, which allows multiple replaces to happen in one pass while preserving full power of string.replace(...).

Disclosure: I am the author. The library was developed to support more complex user-configurable replacements and it addresses all the problematic things like capture groups, backreferences and callback function replacements.

The solutions above are good enough for exact string replacements though.

0

by using prototype function we can replace easily by passing object with keys and values and replacable text

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}'))
Nolequen
  • 3,032
  • 6
  • 36
  • 55
0

All solutions work great, except when applied in programming languages that closures (e.g. Coda, Excel, Spreadsheet's REGEXREPLACE).

Two original solutions of mine below use only 1 concatenation and 1 regex.

Method #1: Lookup for replacement values

The idea is to append replacement values if they are not already in the string. Then, using a single regex, we perform all needed replacements:

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;

Explanations:

  • cat(?=[\s\S]*(dog)) means that we look for "cat". If it matches, then a forward lookup will capture "dog" as group 1, and "" otherwise.
  • Same for "dog" that would capture "goat" as group 2, and "goat" that would capture "cat" as group 3.
  • We replace with "$1$2$3" (the concatenation of all three groups), which will always be either "dog", "cat" or "goat" for one of the above cases
  • If we manually appended replacements to the string like str+"||||cat,dog,goat", we remove them by also matching \|\|\|\|.*$, in which case the replacement "$1$2$3" will evaluate to "", the empty string.

Method #2: Lookup for replacement pairs

One problem with Method #1 is that it cannot exceed 9 replacements at a time, which is the maximum number of back-propagation groups. Method #2 states not to append just replacement values, but replacements directly:

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;

Explanations:

  • (str+"||||,cat=>dog,dog=>goat,goat=>cat") is how we append a replacement map to the end of the string.
  • (\b\w+\b) states to "capture any word", that could be replaced by "(cat|dog|goat) or anything else.
  • (?=[\s\S]*...) is a forward lookup that will typically go to the end of the document until after the replacement map.
    • ,\1=> means "you should find the matched word between a comma and a right arrow"
    • ([^,]*) means "match anything after this arrow until the next comma or the end of the doc"
  • |\|\|\|\|.*$ is how we remove the replacement map.
Mikaël Mayer
  • 10,425
  • 6
  • 64
  • 101
0

We can also use split() and join() methods:

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);
avasuilia
  • 136
  • 4
0

you can try this. buy not smart.

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);
Out put: I have a dog, a goat, and a cat.
0
function strCleaner(realArr,fakeArr,str){

   var i = 0;

   for (; i < fakeArr.length; i++) {
     str = str.replace(fakeArr[i],realArr[i]);
     if(str.includes(fakeArr[i])) i--;
   }
   console.log(str);
   return str;
}
var realArr = ["rezzan","fatih","busra","emir"];
var fakeArr = ["1f","1m","2f","2m"];
var str = "mama is 1f 1f 1f, daddy 1m, daughter is 2f, son is 2m";

strCleaner(realArr,fakeArr,str);

It could be a map or an object but it's very clean and clear.

mfkocak
  • 87
  • 4
-1

I expanded on @BenMcCormicks a bit. His worked for regular strings but not if I had escaped characters or wildcards. Here's what I did

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)

returns "blah blah 234433 blah blah"

This way it will match the key in the mapObj and not the matched word'

Devon
  • 1,019
  • 9
  • 20
Drew Landgrave
  • 1,515
  • 3
  • 13
  • 23
  • // worthless: replaceAll("I have a cat, a dog, and a goat.", { cat:"dog", dog:"goat", goat:"cat" }) // produces: "I have a cat, a cat, and a cat." – Devon Dec 13 '17 at 16:12
-5

Solution with Jquery (first include this file): Replace multiple strings with multiple other strings:

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));
    });
});
Billu
  • 2,733
  • 26
  • 47
  • Does this solution require JQuery? – Anderson Green Jan 16 '18 at 18:56
  • javascript tag added in question, and jquery is a libarary of javascript. – Billu Jan 16 '18 at 20:50
  • 3
    @Super `javascript tag added in question, and jquery is a libarary of javascript.` Hmmm that logic is off, it should be other way round, and also just a heads up - from javascript tag info: "**Unless another tag for a framework/library is also included, a pure JavaScript answer is expected.**" – Traxo Feb 20 '18 at 14:57
  • @Anderson Green, yes jquery needed for above script. – Billu Feb 21 '18 at 06:35
  • @ Traxo, in most web applications we are using framework (bootstrap/google material). Jquery includes in all modern frameworks. So, jquery is necessary item for web applications. – Billu Jun 18 '19 at 11:30
  • @AndersonGreen yes jquery required – Billu Jun 18 '19 at 11:32
  • @SuperModel There is nothing wrong with providing jQuery solution because of how often it is still used, but saying that: `jquery is necessary item for web applications` is just wrong. – Art3mix Sep 29 '19 at 07:47
  • @ Art3mix ok, but I think, Jquery plays a key role in big modern web application to save your time. Using jquery, you can achieve: Write less, do more. – Billu Oct 28 '19 at 06:05