1

I'm writing a bash script that aims to impact all the files in a folder, in order to replace all calls to a given C function by changing the argument. Here is what the current calls look like, and what I want to obtain :

myfunc( foo ) ----> myfunc( foo, foo+1 )

I use the following find/sed command and it does the job:

find . -name "*" -print | xargs sed -i 's/myfunc\([^)]*)\)/myfunc((\1),(\1)+1)/g'

But the issue arise when I have to deal with instructions/arguments that contains parentheses, like in the following instruction:

sqrt( myfunc( (foo+foo)*bar ) );

What happens is that the first closing parenthesis (i.e. the one after foo) is interpreted as the end of the myfunc argument, which it is not...

How can I get a regexp (or any other command) that capture and replace (foo+foo)*bar, i.e. exactly the content of the correct level of parentheses, whatever the number of parentheses levels ?

Silverspur
  • 891
  • 1
  • 12
  • 33

2 Answers2

1

If you are sure your line will only contain myfunc( foo ) and there is no more ) afterwards, you can do a greedy search like this:

myfunc\((.*)\)

See example: http://regex101.com/r/gD1mN0/1

Steven Xu
  • 605
  • 6
  • 12
1
sed ':a
s/myfunc(\([^(]\)(\([^)]*\))/myfunc(\1²\2³/
ta
s/myfunc(\([^)]*\))/myfunc(\1, (\1) + 1 )/g
y/²³/()/
'
  • Try this but it will fail (as is) on recursive call ( myfunc( 1 - myfunc( 2) ) ) on the second myfunc (normaly few use)) but will work on several myfunc (non inclusive) on the line.
  • assume the open and close () are on the same line as myfunc (sed works line per line by default)
  • posix version (--posixon GNU sed)
  • use of marker ²³ so assume not used in code, if any use other unused char or pre-modify and put it back after.

explaination

  • replace any peer of () after myfunc( by respectively ²³. (using recursive call to replace lower level per lower level). after the last substitution you have something like myfunc( subfunc2² subfunc3² arg31, arg32³, arg22³)
  • take the content between () where there is no more ( ) (oops, still could have ( ) in string so buggy on that case) inside and replace with content, content + 1
  • reset any ²³to repsectively ()

Remark: a first round to change (temporary modification with back to original at the end of operation) is needed for any ( or ) that are in string inside myfunc() [not very hard to do but annoying]

NeronLeVelu
  • 9,908
  • 1
  • 23
  • 43