Uma Kanth
Uma Kanth

Reputation: 5629

Regex Handle Bars

I have a string like this

"{{hello}}{{{how}}}{{are}}{{{you}}}"

I need to write a regex to only replace the match

2 braces followed by anything except {}, ends with }}

{{hello}} is valid
{{{how}}} is not. Because it has 3 braces

What I tried [^{}]*{{[^{}]+}}[^{}]* but it doesn't seem to work.

Is there a way to get only the matches with 2 braces.


For example, if I want to replace the matches with empty string.

"{{hello}}{{{how}}{{are}}{{{you}}}"

should become

"{{{how}}}{{{you}}}"

Upvotes: 1

Views: 3152

Answers (2)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 627292

You can use

/(\B|[^{]){{[^{}]*}}(?!})/g

And replace with $1, see this regex demo.

The point here is that the {{...}} that is in the middle of the string should be matched if it is either preceded with a non-word character/start of string (\B) or not a { character ([^{]). Otherwise, consecutive matches won't be found.

JS demo:

var re = /(\B|[^{]){{[^{}]*}}(?!})/g; 
var str = '{{hello}}{{{how}}}{{are}}{{{you}}}\n{{{hello}}}{{how}}{{are}}{{{you}}}';
document.body.innerHTML += "----- Input ------<br/>" + str.replace(/\n/g, "<br/>");
var result = str.replace(re, '$1');
document.body.innerHTML += "<br/>----- Result ------<br/>" + result.replace(/\n/g, "<br/>");

UPDATE

Here is another option for mimicking a negative lookbehind:

var str = '{{hello}}{{{how}}}{{are}}{{{you}}}\n{{{hello}}}{{how}}{{are}}{{{you}}}';
var output = str.replace(/({)?{{[^{}]*}}(?!})/g, function($0, $1){
	return $1 ? $0 : 'x';
});
document.body.innerHTML = output.replace(/\n/g, "<br/>");

If there is a { before {{ it is captured into Group 1 and inside a callback, we check if it was matched. If it was, just put back the whole match, else, only replace the match found.

Upvotes: 1

Avinash Raj
Avinash Raj

Reputation: 174816

alert("{{hello}}{{{how}}}{{are}}{{{you}}}".replace(/(^|[^{])\{\{[^{}]*\}\}(?!\})/g, "$1"))

The above regex should match the string which was surrounded by exactly two curly braces.

  • (^|[^{]) should capture start of the line or any character but not of curly brace.
  • \{\{[^{}]*\}\} matches a double curly braced blocks which looks like {{foo}}, {{bar foo bar}}
  • (?!\}) Negative lookahead which asserts that the match won't be followed by a closing curly brace.

Regex Demo

Upvotes: 4

Related Questions