0

I have the following string and object,

const str = "$(role.name) is $(role) team. $(role.name) started his role as $(role)"

const obj = {
  role: 'Dev',
  'role.name': 'Foo',
}

const expected = "Foo is Dev team.Foo started his role as Dev"

How to using regex ?

My regex ,

const data = str.match(/\$\((.*?)\)/g)
AsZik
  • 55
  • 4
  • 3
    The key is in the title: `replace` – The fourth bird Jun 07 '23 at 10:11
  • Does it have to be `regex`? – Keith Jun 07 '23 at 10:14
  • 2
    It might be easier to start with the object, and then build the output with [a template string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals). – Andy Jun 07 '23 at 10:16
  • See [How can I do string interpolation in JavaScript?](/q/1408289/4642212), [How to replace multiple keywords by corresponding keywords with the `replace` method?](/q/14013223/4642212), [Can ES6 template literals be substituted at runtime (or reused)?](/q/30003353/4642212), and [Defer execution for ES6 Template Literals](/q/22607806/4642212). Use template strings, or use an approach with [`replace`](//developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/replace) with a non-greedy regex and a function as the second argument. – Sebastian Simon Jun 07 '23 at 10:26

3 Answers3

4

Instead of matching, you should replace. As you already have the capture group, you can check if the group 1 exists as a key in the obj.

Note that in your expected there is not space here team.Foo

const str = "$(role.name) is $(role) team. $(role.name) started his role as $(role)"
const regex = /\$\(([^()]*)\)/g;
const obj = {
  role: 'Dev',
  'role.name': 'Foo',
}
const result = str.replace(regex, (m, g1) => obj.hasOwnProperty(g1) ? obj[g1] : m);
console.log(result);
The fourth bird
  • 154,723
  • 16
  • 55
  • 70
2

You can utilize the replace() method with a regular expression pattern.

Here's an example of how you can achieve the desired replacement using the given string and object:

const str = "$(role.name) is $(role) team. $(role.name) started his role as $(role)";

const obj = {
  role: 'Dev',
  'role.name': 'Foo',
};

// Create a regular expression pattern to match the placeholders
const pattern = /\$\(([\w.]+)\)/g;

// Replace the placeholders with the corresponding values from the object
const result = str.replace(pattern, (match, key) => obj[key]);

console.log(result);
// Output: "Foo is Dev team. Foo started his role as Dev"
Keith
  • 22,005
  • 2
  • 27
  • 44
  • See https://stackoverflow.com/editing-help for info on formatting your answer. – 001 Jun 07 '23 at 10:21
  • Hi IGOR, welcome to Stack Overflow, for your first answer that was great, up-vote from me. Like pointed out by 001, it was just your formatting, the comments were easy to understand etc. If you have simple Javascript like this using code snippet `<>` icon in editor you can paste code here and it becomes runnable for everyone to try. I've done this bit for you this time. – Keith Jun 07 '23 at 10:31
2

For a none regex solution, replaceAll is nice and simple.

Please note, as pointed out in comments, although this will work in most cases, be aware that if a replace on one of the passes ends up creating another valid tag in later passes, these will get replaced too. As such I would say the cleanest solution is the regex and the (match, key) callback. I'll leave this answer here as it still might be useful for others to see.

const str = "$(role.name) is $(role) team. $(role.name) started his role as $(role)"

const obj = {
  role: 'Dev',
  'role.name': 'Foo',
}

const fillTemplate = (str, obj) => {
  let ret = str;
  for ([k,v] of Object.entries(obj)) 
    ret = ret.replaceAll(`$(${k})`, v);
  return ret;
}

console.log(fillTemplate(str, obj));
Keith
  • 22,005
  • 2
  • 27
  • 44
  • Note that this will continue replacing the `$(` and `)` delimiters if they occur in the substituted substring; the result also depends on the enumeration order of objects, which isn’t supposed to be relied on. With `const str = "$(a)c$(b)", obj = { a: "$(", b: ")", c: "x" };`, the result will be `"x"`; but with `const str = "$(a)c$(b)", obj = { a: "$(", c: "x", b: ")" };`, it will be `"$(c)"`. – Sebastian Simon Jun 07 '23 at 10:33
  • @SebastianSimon Yeah, that's a good point. Looking at the `regex` example with the `(match, key)` is way better. I'll put a comment in answer on that bit. Cheers.. – Keith Jun 07 '23 at 10:36