barteloma
barteloma

Reputation: 6875

How to format a text using regex in javascript?

I have a text that has format characters in curly braces.

let str = "My name is {name} and age is {age}!";

I want to change this with an object properties.

var myobj = { name: "x", age: "25" }

The result text should be "My name is x and age is 25!"

I can get the name and age values in text using regex.

let regex = /\{([^}]+)\}/g;
let matches = str.match(regex).map(x => x.replace(/[{}]/g, ""));

matches is array ["name", "age"]

But how can I replace with object properties using regex? Is possible a short way?

Upvotes: 1

Views: 2606

Answers (3)

VLAZ
VLAZ

Reputation: 29096

Regular expression

You can use String#replace and specify a function as replacement. This will allow you to replace the matched content if it matches a key or skip it;

function replace(text, obj) {
  let regex = /\{([^}]+)\}/g;
  
  return text.replace(regex, (fullMatch, capture) => {
    //in case no replacement is found, use the initial as default
    let result = fullMatch; 
    
    //see if we have any replacement for this placeholder
    if (capture in obj) {
      result = obj[capture];
    }
    
    //return the value to be used instead of the placeholder
    return result;
  })
}

let str = "My name is {name} and age is {age}!";
let myobj = { name: "x", age: "25" };

console.log(replace(str, myobj));

console.log(replace("Hello, {location} is {age} years old", myobj));

Or much shorter if using the nullish coalescing operator (??). It may not be supported on older environments, so the code might need transpilation for older ones.

function replace(text, obj) {
  return text.replace(
    /\{([^}]+)\}/g, 
    (fullMatch, capture) => obj[capture] ?? fullMatch
  );
}

let str = "My name is {name} and age is {age}!";
let myobj = { name: "x", age: "25" };

console.log(replace(str, myobj));

console.log(replace("Hello, {location} is {age} years old", myobj));

Template literal

You can also just skip the regular expression if it's always the same string but the replacements can differ. Using a template literal and destructuring:

function replace({name, age}) {
  return `My name is ${name} and age is ${age}!`;
}

let myobj = { name: "x", age: "25" };

console.log(replace(myobj));

Upvotes: 2

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 627468

You may use .replace method and get the value from myobj by key that you already capture into Group 1 with your current regex:

let str = "My name is {name} and age is {age} {x}! {missing from myobj}";
var myobj = { name: "x", age: "25", x: ""}
let regex = /{([^{}]+)}/g;
console.log( str.replace(regex, (x,y) => myobj[y] !== undefined ? myobj[y] : x) );
// or a bit more modern variation
console.log( str.replace(regex, (x,y) => myobj[y] ?? x) );

If the key captured is present (myobj[y] ??), the corresponding value will be returned. If there is no key found with the regex in myobj, the whole match will be returned (x). If you need to return a value without braces if the key is not found, use y instead of x here.

There is no need to escape { or } in the pattern since they cannot be parsed as a limiting quantifier (in these cases, JavaScript RegExp engine does some "smart" parsing).

Upvotes: 2

Shuvojit Saha
Shuvojit Saha

Reputation: 382

You can try it String.prototype.replace with a function as parameter.

let str = "My name is {name} and age is {age}!";
var myobj = { name: "x", age: "25" };
let regex = /\{([^}]+)\}/g;
const res = str.replace(regex, (match, key) => myobj[key] || match);
console.log(res);

Upvotes: 1

Related Questions