0

I want to fetch text surrounded by some customized "brackets", i.e.: {{...}} or @(...)@

when the brackets is only one character length (i.e.: {..}) , it is :

/{(.*?)}/g

and there is a more efficient solution, using "not-end-bracket" pattern:

/{([^}]*)}/g

but for two-characsters brackets, only this works

/{{(.*?)}}/g

I can't find an efficient solution like the one in the one-character case.

Is there any?

Visus Zhao
  • 1,104
  • 2
  • 11
  • 25
  • 1
    What happens if you have {{ nested {{ brackets }} ? }} – Kerrek SB Aug 25 '11 at 02:44
  • currently I don't need nested brackets. I only need to levels of brackets, one {..} indicating variables and one @{..}@ indicating js code inside. It's for a simple template. – Visus Zhao Aug 25 '11 at 03:14

2 Answers2

3

I'm assuming you don't need to worry about nesting. If you doo, you shouldn't be using regular expressions.

Here's a way to do what you want without using non-greedy matching (*?):

/{{([^}]|}[^}])*}}/g

In English:

  • two curly braces
  • some number of:
    • a non-curly-brace
    • or a curly brace followed by a non-curly-brace
  • and two close curly braces

This generalizes out to n-curly braces by having n separate branches, one for non-curly, one for a curly and a non-curly, one for two curlies and a non-curly, etc.

In your special case you could just write:

/{{(}?[^}])*}}/g

BTW: the group probably doesn't need to be capturing. eg:

/{{(?:}?[^}])*}}/g
Laurence Gonsalves
  • 125,464
  • 31
  • 220
  • 273
  • Thanks! This saved me from a lot of headache :) – Visus Zhao Aug 25 '11 at 02:58
  • I didn't know about (?:) before. Thanks :) – Visus Zhao Aug 25 '11 at 03:17
  • 1
    @Lawrence: It is trivial to do nested delimiters using patterns, as shown in [this answer](http://stackoverflow.com/questions/4031112/regular-expression-matching/4034386#4034386). You can’t solve `(.+)\1` with a DFA either, but that hasn’t stopped anybody from using it in regexes. The real problem is that Javascript’s patterns are too primitive. Even worse is that you can’t do proper (per UTS#18) Unicode pattern-matching in Javascript, as it’s **the #1 worst** of [all surveyed languages](http://training.perl.com/OSCON2011/index.html) for Unicode pattern matching. Even PHP is better. – tchrist Aug 25 '11 at 03:53
  • 1
    I would add a `+` to the first alternative: `/{{([^}]+|}[^}])*}}/`. Applying that to the string `{{stuff}}`, RegexBuddy says it takes 9 steps to match; without the `+` it takes 17 steps. – Alan Moore Aug 25 '11 at 03:58
  • @tchrist, I'm aware that you can do nesting with non-regular "regex" [sic] patterns in some languages, but you'll note that I said "regular expressions", not "patterns" (and also "shouldn't", not "can't") so the fact that you can do this with non-regular patterns is irrelevant. And yeah, I agree that JavaScript's regex support is pretty bad, but that's what the OP was asking for. I believe that virtually no one would use JavaScript if there was a viable open alternative for browser scripting, but as it is people have to put up with it, and it has very little pressure to improve. – Laurence Gonsalves Aug 31 '11 at 17:06
1

Assuming you have {{...}}

var subject= "{{i am legend}}";
var pattern = /(?:{{)([\w\W]*)(?:}})/;
var text= subject.match(pattern)[1];

You might need to include escaping depending on which "brackets" you choose

user286806
  • 485
  • 1
  • 5
  • 14
  • In most cases, this is going to be much *less* efficient than what the OP started with. It's also incorrect, since it will treat `{{abc}}def{{ghi}}` as one match. – Alan Moore Aug 25 '11 at 04:04