Search code examples
javascriptregexcurly-braces

javascript replace for constructs like {... {..}... }


I want to write a regexp for balanced braces constructs like

{...}, {... {..}...} and {...{..{..}...}..{..}...} where ... means any text, which has no '{' or '}' chars

If I do this:

   txt.replace(/\{[\s\S]+?}/g, function(s){return "_"+s+"_";})

the first } will be considered as end match, so { { } } will become _{ { }_ }

I want a regex to convert this to _{ { } }_

PS: the function(s) part is not from real code, just for example
PPS: I want to do this with regexps if it possible.
PPPS: Highest level of '{' braces included in the text is limited, to 3 or 4 usually

UPDATE: Thanks for comments, Let's limit the number of nested braces to 3. So:

{ { { .. } .. { .. } } .. { .. } }


Solution

  • Thanks for comments, Let's limit the number of nested braces to 3.

    OK, that gives something that we can do with regular expressions. (There are such things as "extended" regular expressions, such as found in Perl or Python, that can match arbitrary nested braces, by using something called "backreferences". I don't know if Javascript's "regular expressions" support those, though.)

    We build up the regular expression in pieces.

    First, let's figure out what a chunk with no nested braces looks like:

    [^{}]*
    

    OK, that was easy. Any number of non-brace characters. :)

    A construct with one level of braces, therefore, looks like

    {[^{}]*}
    

    since we want braces at the beginning and end, and nowhere else.

    How about up to 2 levels?

    Well, then we still have braces at beginning and end, and our content can be "any number of chunks of data, each of which has either 0 or 1 levels of braces".

    So, we put together "0 or 1 levels of braces" by joining those two expressions with | (so that we match one or the other), and put parentheses around that (because we want to treat that as a whole unit) and a * afterward to denote "any number of this thing we just defined between the parentheses". Then braces go around the whole thing. That gives:

    {({[^{}]*}|[^{}]*)*}
      ^^^^^^^^ ^^^^^^
    exp. for   exp. for
    1 level    0 levels
    

    3 levels of braces are left as an exercise. :) Hint: We apply the same logic - braces enclose any number of chunks, each of which has up to 2 levels of braces.