Harry
Harry

Reputation: 54949

regex replace only outer brackets of nested parenthesis

Looking to preserve inner nested brackets when replacing brackets. If possible to make many nested layers work that would be great, if not just nested once is fine.

(if money>5 and (times + total_cash >266))[something]
(if times + total_cash >266)[something]

{if money>5 and (times + total_cash >266)}[something]
{if times + total_cash >266}[something]

A naive attempt doesn't seem to work that well:

str.replace(/\(if(.*?)\)]/gi, '{if $1}')

Upvotes: 2

Views: 952

Answers (1)

Casimir et Hippolyte
Casimir et Hippolyte

Reputation: 89557

for zero level of nesting:

str.replace(/\(if\s*([^()]*)\)/gi, '{if $1}')

for one level (or less):

str.replace(/\(if\s*([^()]*(?:\([^()]*\)[^()]*)*)\)/gi, '{if $1}')

for two levels (or less):

str.replace(/\(if\s*([^()]*(?:\([^()]*(?:\([^()]*\)[^()]*)*\)[^()]*)*)\)/gi, '{if $1}')

etc. This method becomes quickly limited.

Javascript regexes don't have features like recursive patterns (perl, pcre), or a counter system like in .net languages. That's why, the best option is to build a state machine to count the number of opening and closing parenthesis (note that you can use a regex to split your string to interesting parts to do it, for example: str.split(/(\bif\b|[()])/i)).


Note that [^()]*(?:\([^()]*\)[^()]*)* is an optimized way to write: (?:[^()]|\([^()]*\))* (that is shorter but inefficient). This subpattern is unrolled.

Upvotes: 3

Related Questions