I have text, which happens to be code, in which I wish to translate certain known (i.e. hard-coded) function names. The translated functions sometimes have an extra argument, so I cannot simply translate the name, I need to also know what the arguments in parentheses are.
Example of original string (an SQL example):
select appx_median(num) as median from test;
select appx_median(cast(num as int)) as median from test;
Translation I would like:
select percentile_approx(num, 0.5) as median from test;
select percentile_approx(cast(num as int), 0.5) as median from test;
The key thing about this last line is that, as you can see, there needs to be some understanding of the hierarchical / recursive nature of the parentheses being used.
I am trying to use a regex to achieve this (in Scala, though this does not really matter I guess) but am having problems due to the recursive parentheses. In the above example, I know how to translate the first line by using the regex /(appx_median)\(([^\)]*)\)/g, but this does not work for the second. Here is a fiddle which shows the first (successful) and second (failed) translations:
https://regexr.com/6718e
*** EDIT 1 *** Here are some more examples which seem to break the first proposed solutions:
//nesting translatable functions
select appx_median(appx_median(cast(num as int))) as median from test;
//beautifying
select appx_median(
cast(num as int)
) as median from test;
//beautifying and nesting
select appx_median(
appx_median(
cast(num as int)
)
) as median from test;
*** EDIT 2 *** It is apparently not possible to deal with these "nested translations" using regex only. I think that the answer proposed is acceptable for many cases if people are aware of this caveat.
CodePudding user response:
The pattern capture function_name follow by ( , and then capture the same number of ( and ) surrounded by any number of any other character [^()] before reach the end of function and capture ).
appx_median(\(([^()]*([^()]*\([^()]*\)[^()]*)*)\))
Replace with new_function_name ( all the arguments captured by $2 any extra argument and ):
percentile_approx($2,0.5)
Check demo Here
