开发者

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:

  1. we are given a string with values in braces that need replaced
  2. a loop uses "replaceArray" to find all of the values in curly braces that will need replaced
  3. 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜