-1

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
soufiane yakoubi
  • 861
  • 11
  • 31
  • 1
    `$` makes it match till the end. Regex engine parses the string from left to right, so it starts matching from the leftmost char it matches. Use `{(?:{(?:[^{}]*)?)?$`. Or `{{?[^{}]*$`. See [demo](https://regex101.com/r/g32JZb/1). – Wiktor Stribiżew Jun 05 '20 at 08:02

1 Answers1

1

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.

samthegolden
  • 1,366
  • 1
  • 10
  • 26