Ajin
Ajin

Reputation: 291

Vim Substitution

I always wanted to know, how you can substitute within given parameters.

If you have a line like this:

123,Hello,World,(I am, here), unknown

and you wnat to replace World with Foobar then this is an easy task: :%s/World/Foobar/

Now I wonder how I can get rid of a , which is wihtin the ( ).

Theoretically I just have to find the first occurance of ( then substitute the , with a blank until ).

Upvotes: 6

Views: 1807

Answers (5)

Simon C.
Simon C.

Reputation: 1067

Modifying slightly the answer of @Tom can give you a quite good and "a bit" more readable result :

%s/\(.*\)(\(.*\),\(.*\))\(.*\)/\1(\2\3)\4/

That way you will have : in \1 will store what is at the left outside of the parenthesis, \4 what is at the right outside of the parenthesis and \2 and \3 what is inside the parenthesis, respectively on the left (\2) and on the right (\3).

With that you can easily swap your elements if your file is organised as column.

Upvotes: 3

pozitron57
pozitron57

Reputation: 165

Yet another approach, based on the fact that actually you want to substitute only the first occurrence of , inside the parenthesis:

:%s#\((.\{-}\),#\1 #

Explanation:

  • :%s for substitution in the whole file (don't use % if you want to work only with the current line)
  • we can use # or : as a delimiter to make the command more readable
  • in (.\{-} we ask to find any symbol (dot) after the left parenthesis and the rest stands for 0 or more occurrence (as few as possible) of this symbol. This expression is put inside \(...\) to be able to refer to this group as \1 in the future.

Upvotes: 0

andrefs
andrefs

Reputation: 604

You can also select the text you want to change (either with visual or visual-block modes) and enter the : to start the replace command. vi will automatically start the command with :'<,'> which applies the command to the selected area.

Replacing a , can be done with:

:'<,'>s/,/ /g

Upvotes: 1

Tom
Tom

Reputation: 2634

For your example, this is the same thing as suggested by @ubuntuguy

%s/\(.*\)(\(.*\),\(.*\)/\1(\2\3

This will do the exact replacement you want.

Upvotes: 0

Benoit
Benoit

Reputation: 79165

Try lookahead and lookbehind assertions:

%s/([^)]*\zs,\ze.*)//

(\zs and \ze tell where pattern starts and end)

or

%s/\(([^)]*\)\@<=,\(.*)\)\@=//

The first one is more readable, the second one uses \( ... \) groupings with parentheses inside groups which makes it look like obfuscated, and \@<= which apart from being a nice ASCII-art duck is the lookbehind operator, and \@= that is the lookahead operator.

References: :help pattern (more detail at :help /\@=, :help /\ze, etc.)

You use the GUI and want to try those commands? Copy them into the clipboard and run :@+ inside Gvim.

Upvotes: 4

Related Questions