Reputation: 2243
how can i search and replace a function call, but without the arguments of the function?
For short, i will search and replace from foobar(arg1, arg2)
to foobar: arg1, arg2;
My goal is to keep the arg1, arg2
.
How can i solve this? Is there a best practice?
Upvotes: 3
Views: 1030
Reputation: 198556
Try this:
Insert a line at the top of the file - we'll write a macro here. (That's the letter O, not a zero.)
ggO
Instructions for searching for a string of word-characters followed by an open paren, and leave the cursor at the end of the match
/\w*(/e<Ctrl-V><Ctrl-M>
Then we'd go to the matching parenthesis and replace it with a semicolon
%r;
Jump back to the other parenthesis (ctrl-letter O again, not zero)
<Ctrl-V><Ctrl-O>
Replace this parenthesis with :
s:<Space><Ctrl-V><Esc>
Then execute this macro again (assuming it is in the q
register)
@q
Our macro is done, exit insert mode (your line should read: /\w*(/e^M%r;^Os: ^[@q
now)
<Esc>
Pull the line into the q
register (which also removes it from the current file, returning your file to its previous pristine state)
"qdd
Finally, the Big Moment: execute the recursive macro we've built in the @q
register, which will transform the whole file.
@q
BENEFITS: it handles nested functions correctly, since it is not relying on the regular expressions that have trouble capturing parenthesis matching. Instead we rely on the %
command to match parentheses.
Demo:
foo(bar, baz)
foo(foo(bar), baz(), foo(foo, foo, foo))
foo(bar(baz()))
turns into
foo: bar, baz;
foo: foo: bar;, baz: ;, foo: foo, foo, foo;;
foo: bar: baz: ;;;
EDIT: typo (\w
, not \e
in search).
Upvotes: 2
Reputation: 172778
Here's one approach that works with arbitrarily named arguments:
:%s/\(\<foobar\)(\(.*\))/\1: \2;/g
Basically, it captures (via \(...\)
) the function name and the arguments (without the parentheses), and then re-assembles it in a :substitute
command. The \<
asserts a keyword boundary, so that it doesn't match myfoobar(
.
Note that regular expressions are limited in their ability to parse programming language constructs; a proper refactoring tool allows more precise and safer modifications.
One problem in your example is how to deal with the arguments; I've chosen a greedy match (.*
), but this would improperly handle a construct like foobar(arg1, arg2); baz(arg3, arg4)
. A non-greedy match (.\{-}
in Vim), on the other hand, would fail to capture embedded sub-calls like foobar(hostname(), arg2)
. Writing a regular expression to handle all cases is close to impossible, so it's your responsibility to use this wisely (maybe by adding the c
flag to the :substitute
command and acknowledging each replacement manually).
Upvotes: 2
Reputation: 369464
Use following command:
:%s/\v(\w+)\(([^()]*)\)/\1: \2;/g
NOTE This does not work if there nested function call.
See a demo.
Upvotes: 3
Reputation: 9190
You may search for
(foobar)(\()(arg1, arg2)(\))
and replace it with
\1: \3;
So, in VIM it may be something like
:s/(foobar)(\()(arg1, arg2)(\))/\1: \3;/g
Upvotes: 1