Junitar
Junitar

Reputation: 999

Recursive matching when preceded by a given pattern

Consider the following two strings:

a (b (c) d) e
f (g (h) i) j

I would like to match the content in parentheses recursively. I can do so by using the following pattern:

\((?>[^()]|(?R))*\)

This will match both (b (c) d) and (g (h) i).

Now, let's say I want to match recursively the content in parentheses only when preceded by the letter a. How can I do that?

Using (?<=a\s)\((?>[^()]|(?R))*\) does not seem to work.

Upvotes: 1

Views: 87

Answers (2)

The fourth bird
The fourth bird

Reputation: 163642

Instead of repeating the whole pattern, you could repeat create a capturing group and repeat the first sub pattern instead:

(?<=a\s)(\((?>[^()]|(?1))*\))
  • (?<=a\s) Assert what is on the left is a and a whitespace char
  • ( Capture group 1
    • \( Match (
    • (?> Atomic group
      • [^()] Match any char except ( or ) (Use [^()]+ to make it more efficient)
      • | Or
      • (?1) Recurse the first subpattern
    • )* Close atomic group and repeat 0+ times
    • \) Match )
  • ) Close group 1

Regex demo

When adding a capturing group, we can omit the lookbehind and match a and a whitespace char:

a\s(\((?>[^()]|(?1))*\))

Regex demo

Upvotes: 1

rags2riches-prog
rags2riches-prog

Reputation: 1761

Update: This solution should do the trick

(?:a\s)(\((?>[^()]|(?1))*\))

tested with your own strings:

a (b (c) d) e = true

f (g (h) i) j = false

a (b (c) d (f) g) e = true

Let me know if this works and if not why not.

Upvotes: 0

Related Questions