Replacing Text Inside of Curley Braces JavaScript
I am trying to use JavaScript to dynamically replace content inside of curly braces. Here is an example of my code:
var myString = "This is {name}'s {adjective} {type} in JavaScript! Yes, a {type}!";
var replaceArray = ['name', 'adjective', 'type'];
var replaceWith = ['John', 'simple', 'string'];
for(var i = 0; i <= replaceArray.length - 1; i ++) {
myString.replace(/\{replaceArray[i]\}/gi, replaceWith[i]);
}
alert(myString);
The above code, should, output "This is John's simple string in JavaS开发者_高级运维cript! Yes, a string!".
Here is what happens:
- we are given a string with values in braces that need replaced
- a loop uses "replaceArray" to find all of the values in curly braces that will need replaced
- these values, along with the curly braces, will be replaced with the corresponding values in the "replaceWith" array
However, I am not having any luck, especially since one value may be replaced in multiple locations, and that I am dealing a dynamic value inside of the regular expression.
Can anyone help me fix this, using a similar setup as above?
First, String.replace
is not destructive - it doesn't change the string itself, so you'll have to set myString = myString.replace(...)
. Second, you can create RegExp
objects dynamically with new RegExp
, so the result of all that would be:
var myString = "This is {name}'s {adjective} {type} in JavaScript! Yes, a {type}!",
replaceArray = ['name', 'adjective', 'type'],
replaceWith = ['John', 'simple', 'string'];
for(var i = 0; i < replaceArray.length; i++) {
myString = myString.replace(new RegExp('{' + replaceArray[i] + '}', 'gi'), replaceWith[i]);
}
The best way I have found to do this, is to use an in-line replace function like others have mentioned, and from whom I borrowed. Special shout out to @yannic-hamann for the regex and clear example. I am not worried about performance, as I am only doing this to construct paths.
I found my solution in MDN's docs.
const interpolateUrl = (string, values) => string.replace(/{(.*?)}/g, (match, offset) => values[offset]);
const path = 'theresalways/{what}/inthe/{fruit}-stand/{who}';
const paths = {
what: 'money',
fruit: 'banana',
who: 'michael',
};
const expected = 'theresalways/money/inthe/banana-stand/michael';
const url = interpolateUrl(path, paths);
console.log(`Is Equal: ${expected === url}`);
console.log(`URL: ${url}`)
Strings are immutable
Strings in JavaScript are immutable. It means that this will never work as you expect:
myString.replace(x, y);
alert(myString);
This is not just a problem with .replace()
- nothing can mutate a string in JavaScript. What you can do instead is:
myString = myString.replace(x, y);
alert(myString);
Regex literals don't interpolate values
Regular expression literals in JavaScript don't interpolate values so this will still not work:
myString = myString.replace(/\{replaceArray[i]\}/gi, replaceWith[i]);
You have to do something like this instead:
myString = myString.replace(new RegExp('\{'+replaceArray[i]+'\}', 'gi'), replaceWith[i]);
But this is a little bit messy, so you may create a list of regexes first:
var regexes = replaceArray.map(function (string) {
return new RegExp('\{' + string + '\}', 'gi');
});
for(var i = 0; i < replaceArray.length; i ++) {
myString = myString.replace(regexes[i], replaceWith[i]);
}
As you can see, you can also use i < replaceArray.length
instead of i <= replaceArray.length - 1
to simplify your loop condition.
Update 2017
Now you can make it even simpler:
var regexes = replaceArray.map(string => new RegExp(`\{${string}\}`, 'gi'));
for(var i = 0; i < replaceArray.length; i ++) {
myString = myString.replace(regexes[i], replaceWith[i]);
}
Without a loop
Instead of looping and applying .replace()
function over and over again, you can do it only once like this:
var mapping = {};
replaceArray.forEach((e,i) => mapping[`{${e}}`] = replaceWith[i]);
myString = myString.replace(/\{\w+\}/ig, n => mapping[n]);
See DEMO.
Templating engines
You are basically creating your own templating engine. If you want to use a ready solution instead, then consider using:
- John Resig's Micro-Templating
- Mustache
- jQuery Templates
- Handlebars
- doT.js
or something like that.
An example of what you are trying to do using Mustache would be:
var myString = "This is {{name}}'s {{adjective}} {{type}} in JavaScript! Yes, a {{type}}!";
var myData = {name: 'John', adjective: 'simple', type: 'string'};
myString = Mustache.to_html(myString, myData);
alert(myString);
See DEMO.
Here's a function that takes the string and an array of replacements. It's flexible enough to be re-used. The only catch is, you need to use numbers in your string instead of strings. e.g.,
var str = "{0} membership will start on {1} and expire on {2}.";
var arr = ["Jamie's", '11/27/14', '11/27/15'];
function personalizeString(string, replacementArray) {
return string.replace(/{(\d+)}/g, function(match, g1) {
return replacementArray[g1];
});
}
console.log(
personalizeString(str, arr)
)
Demo: https://jsfiddle.net/4cfy7qvn/
I really like rsp's answer. Especially the 'Without a loop' section. Nonetheless, I find the code not that intuitive. I understand that this question comes from the two arrays scenario and that is more than 7 years old, but since this question appears as #1 on google when searching to replace a string with curly braces and the author asked for a similar setup I am tempted to provide another solution.
That being said, a copy and paste solution to play around with:
var myString = "This is {name}'s {adjective} {TYPE} in JavaScript! Yes, a { type }!";
var regex = /{(.*?)}/g;
myString.replace(regex, (m, c) => ({
"name": "John",
"adjective": "simple",
"type": "string"
})[c.trim().toLowerCase()]);
This resource really helped me to build and understand the code above and to learn more about regex with JavaScript in general.
精彩评论