Asked  7 Months ago    Answers:  5   Viewed   55 times

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

 Answers

66

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);
Tuesday, June 1, 2021
 
lena
answered 7 Months ago
15

You could extend the String object with your own function that does what you need (useful if there's ever missing functionality):

String.prototype.replaceArray = function(find, replace) {
  var replaceString = this;
  for (var i = 0; i < find.length; i++) {
    replaceString = replaceString.replace(find[i], replace[i]);
  }
  return replaceString;
};

For global replace you could use regex:

String.prototype.replaceArray = function(find, replace) {
  var replaceString = this;
  var regex; 
  for (var i = 0; i < find.length; i++) {
    regex = new RegExp(find[i], "g");
    replaceString = replaceString.replace(regex, replace[i]);
  }
  return replaceString;
};

To use the function it'd be similar to your PHP example:

var textarea = $(this).val();
var find = ["<", ">", "n"];
var replace = ["&lt;", "&gt;", "<br/>"];
textarea = textarea.replaceArray(find, replace);
Tuesday, June 1, 2021
 
hohner
answered 7 Months ago
73

If you build your multiple line text with "n"s, this will work with a simple sed command as:

DATA=`echo ${DATA} | tr 'n' "\n"`
#now, DATA="line1nline2nline3"
sed "s/_data_/${DATA}/" mail.tpl
Thursday, June 3, 2021
 
Silfverstrom
answered 7 Months ago
64

You can use the sticky flag y (but Internet Explorer doesn't support it):

s = s.replace(/(^https?://.*?/path1/?|(?!^))./gy, '$1*')

But the simplest (and that is supported everywhere), is to use a function as replacement parameter.

s = s.replace(/^(https?://.+/path1/?)(.*)/, function (_, m1, m2) {
    return m1 + '*'.repeat(m2.length);
});

For the second case, you can simply check if there's an @ after the current position:

s = s.replace(/.(?=.*@)/g, '*');
Thursday, August 19, 2021
 
penpen
answered 4 Months ago
23

You could match all of the above with:

b[dX][-. dX]+(d{4})b

... and replace it with * x strlen(match) - 4 + 1, see a demo on regex101.com.


In JavaScript:
var string = "Hi, my account number is 1234 5678 9012 2345 and I'm great.";
var new_string = string.replace(/b[dX][-. dX]+(d{4})b/g, function(match, capture) {
    return Array(match.length-4).join("*") + capture;
});
print(new_string);

See a demo on ideone.com.

Wednesday, October 20, 2021
 
Yrtymd
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share