1

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?

3
  • 2
    Just to verify, does it have to be regex? A template literal can do it easier: `My name is {myobj.name} and age is {myobj.age}!` or even `My name is {name} and age is {age}!` if you make sure name and age are variables. Commented Jun 23, 2020 at 9:20
  • 2
    str.replace(regex, (x,y) => myobj[y] ? myobj[y] : x) Commented Jun 23, 2020 at 9:21
  • 1
    @VLAZ, I need regex solution, I know your solution. Commented Jun 23, 2020 at 9:29

3 Answers 3

2

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

Sign up to request clarification or add additional context in comments.

4 Comments

myobj[y] || x makes more cleaner
@User863 it can also trigger by accident if the replacement is an empty string.
@VLAZ The replacement is a callable here, it is not an empty string. [^{}]+ matches one or more chars, there will always be some text in between curly braces, so there will be no chance of searching for an empty string key.
@WiktorStribiżew I meant if myobj[y] is an empty string, that is falsey, so it will return the placeholder, instead of removing it. str = "hello {foo}"; myobj = { foo: "" } for example.
2

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));

Comments

1

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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.