How would I use TreeWalker Method to replace multiple words [duplicate] - javascript
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".
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.
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);
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])
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'
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
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"
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.'
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.
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, '{')
);
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.
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."
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.
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;
}
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/
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))
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,'}');
I have modified Ben McCormick's answer to work with your new test case.
I simply added word boundaries to the regular expression:
/\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);
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
}
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/
<!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=' ';}
if(x=='car'){return x='BMW'}
else{return x;}//must need
});
document.getElementById("demo").innerHTML = res;
}
</script>
</body>
</html>
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"
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."
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.
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}'))
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.
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);
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.
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'
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));
});
});
Related
Transform string of text using JavaScript
I am working on a code to transform a string of text into a Sentence case which would also retain Acronyms. I did explore similar posts in StackOverflow, however, I couldn't find the one which suits my requirement. I have already achieved the transformation of Acronyms and the first letter in the sentence. however, I ran into other issues like some letters in the sentence are still in Uppercase, especially texts in and after Double Quotes (" ") and camelcase texts. Below is the code I am currently working on, I would need someone to help me Optimize the code and to fix the issues. String.prototype.toSentenceCase = function() { var i, j, str, lowers, uppers; str = this.replace(/(^\w{1}|\.\s*\w{1})/gi, function(txt) { return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); }); // Certain words such as initialisms or acronyms should be left uppercase uppers = ['Id', 'Tv', 'Nasa', 'Acronyms']; for (i = 0, j = uppers.length; i < j; i++) str = str.replace(new RegExp('\\b' + uppers[i] + '\\b', 'g'), uppers[i].toUpperCase()); // To remove Special caharacters like ':' and '?' str = str.replace(/[""]/g,''); str = str.replace(/[?]/g,''); str = str.replace(/[:]/g,' - '); return str; } Input: play around: This is a "String" Of text, which needs to be cONVERTED to Sentence Case at the same time keeping the Acronyms as it is like Nasa. Current Output: Play around - This is a String Of text, which needs to be cONVERTED to Sentence Case at the same time keeping the ACRONYMS as it is like NASA. Expected Output: Play around - this is a string of text, which needs to be converted to sentence case at the same time keeping the ACRONYMS as it is like NASA.
Here's a runnable version of the initial code (I have slightly modified the input string): String.prototype.toSentenceCase = function() { var i, j, str, lowers, uppers; str = this.replace(/(^\w{1}|\.\s*\w{1})/gi, function(txt) { return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); }); // Certain words such as initialisms or acronyms should be left uppercase uppers = ['Id', 'Tv', 'Nasa', 'Acronyms']; for (i = 0, j = uppers.length; i < j; i++) str = str.replace(new RegExp('\\b' + uppers[i] + '\\b', 'g'), uppers[i].toUpperCase()); // To remove Special caharacters like ':' and '?' str = str.replace(/[""]/g,''); str = str.replace(/[?]/g,''); str = str.replace(/[:]/g,' - '); return str; } const input = `play around: This is a "String" Of text, which needs to be cONVERTED to Sentence Case at the same time keeping the Acronyms as it is like Nasa. another sentence. "third" sentence starting with a quote.` const result = input.toSentenceCase() console.log(result) I ran into other issues like some letters in the sentence are still in Uppercase, especially texts in and after Double Quotes (" ") and camelcase texts. Some letters remain uppercased because you are not calling .toLowerCase() anywhere in your code. Expect in the beginning, but that regex is targetingonly the initial letters of sentences, not other letters. It can be helpful to first lowercase all letters, and then uppercase some letters (acronyms and initial letters of sentences). So, let's call .toLowerCase() in the beginning: String.prototype.toSentenceCase = function() { var i, j, str, lowers, uppers; str = this.toLowerCase(); // ... return str; } Next, let's take a look at this regex: /(^\w{1}|\.\s*\w{1})/gi The parentheses are unnecessary, because the capturing group is not used in the replacer function. The {1} quantifiers are also unnecessary, because by default \w matches only one character. So we can simplify the regex like so: /^\w|\.\s*\w/gi This regex finds two matches from the input string: p . a Both matches contain only one letter (\w), so in the replacer function, we can safely call txt.toUpperCase() instead of the current, more complex expression (txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()). We can also use an arrow function: String.prototype.toSentenceCase = function() { var i, j, str, lowers, uppers; str = this.toLowerCase(); str = str.replace(/^\w|\.\s*\w/gi, (txt) => txt.toUpperCase()); // ... return str; } However, the initial letter of the third sentence is not uppercased because the sentence starts with a quote. Because we are anyway going to remove quotes and question marks, let's do it at the beginning. Let's also simplify and combine the regexes: // Before str = str.replace(/[""]/g,''); str = str.replace(/[?]/g,''); str = str.replace(/[:]/g,' - '); // After str = str.replace(/["?]/g,''); str = str.replace(/:/g,' - '); So: String.prototype.toSentenceCase = function() { var i, j, str, lowers, uppers; str = this; str = str.toLowerCase(); str = str.replace(/["?]/g,''); str = str.replace(/:/g,' - '); str = str.replace(/^\w|\.\s*\w/gi, (txt) => txt.toUpperCase()); // ... return str; } Now the initial letter of the third sentence is correctly uppercased. That's because when we are uppercasing the initial letters, the third sentence doesn't start with a quote anymore (because we have removed the quote). What's left is to uppercase acronyms. In your regex, you probably want to use the i flag as well for case-insensitive matches. Instead of using a for loop, it's possible to use a single regex to look for all matches and uppercase them. This allows us to get rid of most of the variables as well. Like so: String.prototype.toSentenceCase = function() { var str; str = this; str = str.toLowerCase(); str = str.replace(/["?]/g,''); str = str.replace(/:/g,' - '); str = str.replace(/^\w|\.\s*\w/gi, (txt) => txt.toUpperCase()); str = str.replace(/\b(id|tv|nasa|acronyms)\b/gi, (txt) => txt.toUpperCase()); return str; } And looks like we are now getting correct results! Three more things, though: Instead of creating and mutating the str variable, we can modify this and chain the method calls. It might make sense to rename the txt variables to match variables, since they are regex matches. Modifying a built-in object's prototype is a bad idea. Creating a new function is a better idea. Here's the final code: function convertToSentenceCase(str) { return str .toLowerCase() .replace(/["?]/g, '') .replace(/:/g, ' - ') .replace(/^\w|\.\s*\w/gi, (match) => match.toUpperCase()) .replace(/\b(id|tv|nasa|acronyms)\b/gi, (match) => match.toUpperCase()) } const input = `play around: This is a "String" Of text, which needs to be cONVERTED to Sentence Case at the same time keeping the Acronyms as it is like Nasa. another sentence. "third" sentence starting with a quote.` const result = convertToSentenceCase(input) console.log(result)
How can I split commas and periods from words inside of string using split?
I am trying to change specific word in a string with something else. For example, I want to change 'John' in let name = 'Hi, my name is John.'; to 'Jack'. I know how to split a string by words or characters. I also know how to remove commas, periods, and other symbols in a string. However, if I split the given string with a separator (" "), I will have 'John.' which I do not want. (I know I can switch 'John.' with 'Jack.' but assume that I have an key and value pairs in an object and I am using the values which are names {Father: Jack, Mother: Susan, ...} I don't know how to separate a string word by word including commas and periods. For example, if I was given an input which is a string: 'Hi, my name is John.' I want to split the input as below: ['Hi', ',', 'my', 'name', 'is', 'John', '.'] Does anyone know how to do it? Below is the challenge I am working on. Create a function censor that accepts no arguments. censor will return a function that will accept either two strings, or one string. When two strings are given, the returned function will hold onto the two strings as a pair, for future use. When one string is given, the returned function will return the same string, except all instances of a first string (of a saved pair) will be replaced with the second string (of a saved pair). //Your code here const changeScene = censor(); changeScene('dogs', 'cats'); changeScene('quick', 'slow'); console.log(changeScene('The quick, brown fox jumps over the lazy dogs.')); // should log: 'The slow, brown fox jumps over the lazy cats.'
I think your real question is "How do I replace a substring with another string?" Checkout the replace method: let inputString = "Hi, my name is John."; let switch1 = ["John", "Jack"]; let switched = inputString.replace(switch1[0], switch1[1]); console.log(switched); // Hi, my name is Jack. UPDATE: If you want to get ALL occurrences (g), be case insensitive (i), and use boundaries so that it isn't a word within another word (\\b), you can use RegExp: let inputString = "I'm John, or johnny, but I prefer john."; let switch1 = ["John", "Jack"]; let re = new RegExp(`\\b${switch1[0]}\\b`, 'gi'); console.log(inputString.replace(re, switch1[1])); // I'm Jack, or johnny, but I prefer Jack.
You can Try This ... var string = 'Hi, my name is John.'; //var arr = string.split(/,|\.| /); var arr = string.split(/([,.\s])/); console.log(arr);
Using 'Hi, my name is John.'.split(/[,. ]/); will do the job. It will split commas and periods and spaces. Edit: For those who want to keep the comma and period, here is my wildly inefficient method. var str = 'Hi, my name is John.' str = str.replace('.', 'period'); str = str.replace(',', 'comma'); str = str.split(/[,. ]/); for (var i = 0; i < str.length; i++) { if (str[i].indexOf('period') > -1) { str[i] = str[i].replace('period', ''); str.splice(i+1, 0, "."); } else if (str[i].indexOf('comma') > -1) { str[i] = str[i].replace('comma', ''); str.splice(i+1, 0, ","); } } console.log(str);
Searching for words in string
I'm trying to make a function that finds the string that contains all words from an array. I have tried this: function multiSearchOr(text, searchWords){ var searchExp = new RegExp(searchWords.join("|"),"gi"); return (searchExp.test(text))?"Found!":"Not found!"; } alert(multiSearchOr("Hello my name sam", ["Hello", "is"])) But this only alert "Found" when one of the words have been found. I need it to alert me when all the words are in the string. An example: var sentence = "I love cake" var words = ["I", "cake"]; I want the application to alert me when it finds all of the words from the array in the string sentence. Not when it only found one of the words.
If you're interested in using only a single regular expression, then you need to use a positive lookahead when constructing your expression. It will look something like that: '(?=\\b' + word + '\\b)' Given this construction, you can then create your regular expression and test for the match: function multiSearchOr(text, searchWords){ var regex = searchWords .map(word => "(?=.*\\b" + word + "\\b)") .join(''); var searchExp = new RegExp(regex, "gi"); return (searchExp.test(text))? "Found!" : "Not found!"; }
Here's a working example. You simply need to iterate over the array and compare if the words are present in the string or not using indexOf(). if it is not equal then alert Not found otherwise alert Found. function multiSearchOr(text, searchWords){ for(var i=0; i<searchWords.length; i++) { if(text.indexOf(searchWords[i]) == -1) return('Not Found!'); } return('Found!'); } alert(multiSearchOr("Hello my name sam", ["Hello", "is"]));
Is this what are you looking for ? In this way, you can use more complex sentences that contain non-alphanumeric characters. var sentence = "Hello, how are you ?" var test1 = ["Hello", "how", "test"]; var test2 = ["hello", "How"]; function multiSearchOr(text, searchWords){ if (text && searchWords) { var filteredText = text.match(/[^_\W]+/g); if (filteredText !== null) { var lowerCaseText = filteredText.map(function(word) { return word.toLowerCase(); }); for (var i = 0; i < searchWords.length; i++) { if (lowerCaseText.indexOf(searchWords[i].toLowerCase()) === -1) { return "Not found!"; } } return "Found!" } return "Error: the text provided doesn't contain any words!" } return "Error: Props are missing"; } console.log(multiSearchOr(sentence, test1)); console.log(multiSearchOr(sentence, test2));
if all(word in text for word in searchWords): print('found all') if any(word in text for word in searchWords): print('found at least one') all() if you want that all the word in the list searchWords are in the text any() if it's enough that one list word is in the text
Here is a version that will split the sentense you pass and check each word const matchAllEntries = (arr, target) => target.every(v => arr.includes(v)); const arr = ['lorem', 'ipsum', 'dolor']; const strs = ['lorem blue dolor sky ipsum', 'sky loremdoloripsum blue', 'lorem dolor ipsum']; strs.forEach(str => { // split on non alphabet and numbers (includes whitespace and puntuation) parts = str.split(/\W/); console.log(matchAllEntries(arr, parts)); })
Replace multiple strings with multiple other strings
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".
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.
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);
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])
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'
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
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"
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.'
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. 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, '{') ); 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.
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."
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.
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; }
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/
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))
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,'}');
I have modified Ben McCormick's answer to work with your new test case. I simply added word boundaries to the regular expression: /\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);
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 }
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/
<!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=' ';} if(x=='car'){return x='BMW'} else{return x;}//must need }); document.getElementById("demo").innerHTML = res; } </script> </body> </html>
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"
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."
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.
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}'))
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.
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);
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.
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'
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)); }); });
JavaScript - string regex backreferences
You can backreference like this in JavaScript: var str = "123 $test 123"; str = str.replace(/(\$)([a-z]+)/gi, "$2"); This would (quite silly) replace "$test" with "test". But imagine I'd like to pass the resulting string of $2 into a function, which returns another value. I tried doing this, but instead of getting the string "test", I get "$2". Is there a way to achieve this? // Instead of getting "$2" passed into somefunc, I want "test" // (i.e. the result of the regex) str = str.replace(/(\$)([a-z]+)/gi, somefunc("$2"));
Like this: str.replace(regex, function(match, $1, $2, offset, original) { return someFunc($2); })
Pass a function as the second argument to replace: str = str.replace(/(\$)([a-z]+)/gi, myReplace); function myReplace(str, group1, group2) { return "+" + group2 + "+"; } This capability has been around since Javascript 1.3, according to mozilla.org.
Using ESNext, quite a dummy links replacer but just to show-case how it works : let text = 'Visit http://lovecats.com/new-posts/ and https://lovedogs.com/best-dogs NOW !'; text = text.replace(/(https?:\/\/[^ ]+)/g, (match, link) => { // remove ending slash if there is one link = link.replace(/\/?$/, ''); return `${link.substr(link.lastIndexOf('/') +1)}`; }); document.body.innerHTML = text;
Note: Previous answer was missing some code. It's now fixed + example. I needed something a bit more flexible for a regex replace to decode the unicode in my incoming JSON data: var text = "some string with an encoded 's' in it"; text.replace(/&#(\d+);/g, function() { return String.fromCharCode(arguments[1]); }); // "some string with an encoded 's' in it"
If you would have a variable amount of backreferences then the argument count (and places) are also variable. The MDN Web Docs describe the follwing syntax for sepcifing a function as replacement argument: function replacer(match[, p1[, p2[, p...]]], offset, string) For instance, take these regular expressions: var searches = [ 'test([1-3]){1,3}', // 1 backreference '([Ss]ome) ([A-z]+) chars', // 2 backreferences '([Mm][a#]ny) ([Mm][0o]r[3e]) ([Ww][0o]rd[5s])' // 3 backreferences ]; for (var i in searches) { "Some string chars and many m0re w0rds in this test123".replace( new RegExp( searches[i] function(...args) { var match = args[0]; var backrefs = args.slice(1, args.length - 2); // will be: ['Some', 'string'], ['many', 'm0re', 'w0rds'], ['123'] var offset = args[args.length - 2]; var string = args[args.length - 1]; } ) ); } You can't use 'arguments' variable here because it's of type Arguments and no of type Array so it doesn't have a slice() method.