Reputation: 32776
I'm struggling to figure out how to get this regex to work without needing a loop. Here's the code that works:
var template = {name: "Oscar", anotherName: "your twin", hello: 'world'}
var str = "Hello, {{name}} I'm {{anotherName}}. Hello to the {{hello}}"
Object.keys(template).forEach(function (keyName) {
pattern = new RegExp('{{' + keyName + '}}', 'g');
str = str.replace(pattern, template[keyName]);
})
// => str "Hello, Oscar I'm your twin. Hello to the world"
The thing about this code I don't like is that it's in a loop generating regex when I feel like a regex should be able to handle this use case. However, my regex is always only matching the last item. I was doing regex like str.match(/({{.}})/gi)
but then only the {{hello}}
was getting matched.
Preferably I'd like to do something where I can get all matches in an array and then map the array like matchesFromRegex.map(match => template[match]).join('')
Also, I'm in an vanilla JS environment so .matchAll
(which isn't supported in IE) wouldn't work.
Upvotes: 0
Views: 25
Reputation: 78920
In a RegExp string, {
has a special meaning (it lets you set a cardinality for a match, like \d{5}
for five digits).
Use new RegExp('\\{\\{' + keyName + '}}', 'g');
instead. The double backslash in JavaScript will create a backslash, which will escape the {
character.
If you want to avoid the loop, you can use the function-based version of replace
instead:
const pattern = /\{\{([^}]*)}}/g;
str.replace(pattern, (_, key) => template[key]);
To break it down, pattern
has a capture group (the parts in ()
). The String.prototype.replace
function can let you supply a function for doing replacements, which will be passed your match results.
Upvotes: 2