Search code examples
javascriptnode.jsregexstringregex-group

Regex: Lazy matching in nested groups


I have this regex: /{(?:{(?:.*?)?)?$/g.

Notice that I'm trying to lazily match .*? in the innermost group.

But it doesn't behave the way I expect:

const regex = /{(?:{(?:.*?)?)?$/g;

let match = "{{abc{".match(regex)
// expected: [ "{" ]
// actual: [ "{{abc{" ]

match = "{{abc{{".match(regex)
// expected: [ "{{" ]
// actual: [ "{{abc{{" ]

match = "{{abc{{def".match(regex)
// expected: [ "{{def" ]
// actual: [ "{{abc{{def" ]

I'm using this regex to match {, {{ or {{something if it is at the end of a string (without taking into account multi-line strings)

It might be because the string is matched from left to right, but is there an elegant way to get the expected behavior?




EDIT:

Using the regex in the selected solution solves the above problem, but fails if the string after the last {{ contains one or many { not following each other.

example:

const regex = /{(?:{(?:[^{]*?)?)?$/g;

let match = "{{abc{{de{f".match(regex)
// expected: [ "{{de{f" ]
// actual: null

match = "{{abc{{de{f{g".match(regex)
// expected: [ "{{de{f{g" ]
// actual: null

Solution

  • With .* you are matching everything, including {. You have to exclude it from the "innermost string" with a [^{], and you may add here any character you also want to exclude:

    {(?:{(?:[^{]*?)?)?$.

    Check it here.

    For the EDIT, you need to make one of the { optional, in order to be able to parse both {{ and {.

    {(?:{?(?:[^{]*?)?)?$.

    Check it here.