Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace java function using regex: matching nested brackets

Tags:

java

regex

I want to replace a function definition and declaration using Regex, i.e.,

replace

public abstract void myFuction(MyParam myParam);

or

@Override
public void myFuction(MyParam myParam){

}

I tried with this regex:

(@Override[\n\s\t]*)?public *(abstract)? *void
*generateProcessMethod *\(UIGenerationContext *[^)]+\)[\n\\s\t]*((\{[^{}]*?\})|;)

But the problem is if the function has any other { or } then it will not work.

Replacing [^{}] with . is not a solution as it replaces the following functions also.

like image 818
Abin Manathoor Devasia Avatar asked Mar 25 '23 09:03

Abin Manathoor Devasia


1 Answers

Using regular expressions, this (bracket nesting) does can be done, but only up to a fixed level of nesting.

Your current regex (changed a bit):

(@Override[\n\s\t]*)?public *(abstract)? *void *[a-z]*\([a-z]* [^)]+\)[\n\\s\t]*((\{[^\{\}]*?\})|;)

Only allows one level. More specifically, this is the part that matches it:

(\{[^\{\}]*?\})

If you wanted to match up to two levels, change the mentioned part to:

(\{([^{}]*|\{[^{}]*\})*\})

Thus:

(@Override[\n\s\t]*)?public *(abstract)? *void *[a-z]*\([a-z]* [^)]+\)[\n\\s\t]*(\{([^{}]*|\{[^{}]*\})*\}|;)

To add more levels, you have to keep editing. It will get messier and messier as you add levels.

Explanation:

  • \{ will match the first opening bracket
    • ( opens a group
      • [^{}]* matches anything other than brackets
      • | or
      • \{ if it does find an opening bracket...
        • [^{}]* ...it will match anything other than a bracket...
      • \} ...until it finds a closing bracket
    • ) closes the group
    • * the above group can happen zero or more times
  • \} matches the ending bracket

To add more levels, change the middle (second) [^{}]* part to ([^{}]*|\{[^{}]*\})*.

If you can't predict the maximum nesting level:

There are some languages that allow the nesting operator R, which allows you to nest arbitrary number of levels. If your language does not support it (Java doesn't, afaik PHP and Perl do), you'll have to either:

  • predict the maximun nesting level; OR
  • create a parser yourself.

Regular expressions, without the R operator, cannot nest an arbitrary number of levels.

That said, using the R operator would be as such:

(\{([^{}]|(?R))*\})

More info at this answer.

like image 84
acdcjunior Avatar answered Apr 01 '23 11:04

acdcjunior