91

Say I have ten lines and I want to prepend text to some word that occurs in those lines? It does not have to be at the beginning of the line.

From:

sdfsd   foo sdfsd
sfsd    foo fsdf
sdfsdf  foo  sdfsdf

to:

sdfsd   bar(foo sdfsd
sfsd    bar(foo fsdf
sdfsdf  bar(foo  sdfsdf

Is it also possible to not only prepend the bar( but actually surround foo with bar(foo)?

I would also like a quick way to append // comments to multiple lines (C-style comments).

I use Vim/GVim 7.2.

Allen
  • 447
  • 6
  • 20

7 Answers7

169

Go to the first foo, press Ctrl-v to enter visual block mode and press down until all the lines with foo are marked. Then press Shift-i to insert at the beginning (of the block). When you are finished and press Esc, the inserted characters will be added to each line at the left of the marked block.

To insert at the end, press again Ctrl-v, move up/down to mark all affected lines and then press End or $ to extend the selection until the end of the lines. Now you can press Shift-a to append at the end of all the lines, just like previously with Shift-i.

The visual selection can also be done with normal movement commands. So to comment a whole block in C you could move to the opening brace and type Ctrl-v % Shift-i // Esc.

sth
  • 200,334
  • 49
  • 262
  • 354
  • 5
    Just an addition: if Ctrl-V does not start visual block mode in Vim on Windows, one should use Ctrl-Q instead. – Paul Jul 23 '09 at 20:53
  • 3
    A variation of then answer is to mark visual block with shift+V thenalter the block in ex mode: :'s/^/prexix_text/ :'s/$/suffix_text/ Note than "'" is printed automatically by vim when you press ":". – dimba Jul 23 '09 at 20:57
  • 1
    To uncomments use visual block (mark with Ctrl+V). One the column with comment sign "//" is marked press "d" to remove the comments. dont forget about C++ comments (/**/) too :) – dimba Jul 23 '09 at 20:59
  • 9
    It's worth noting in Linux I had to escape out of Insert mode before the prefix applied to all lines, and it is a capital I needed to go into insert mode from Visual mode - i.e. Shift+I, type prefix, Escape, Escape. – Joshua Enfield Oct 06 '11 at 07:17
  • 6
    This doesn't work on putty. When I press `i` nothing happens. When I press `shift+i` the selection disappears but I am able to insert text (on the current place where the cursor is only). – Jürgen Paul Jul 26 '12 at 07:14
  • Since the visual selection in step 2 is the same as in step 1, you can avoid monotony by typing `gv` instead. – gmeben Apr 19 '13 at 14:10
  • 1
    I think some people might be getting the impression that you have to press escape more than once because of the slight delay after pressing Escape, wait a moment and the changes will be there, only need to press escape once, exactly as it is said in his answer (exactly). And new users dont forget, if your commenting shell scripts using #, that # is also a highlight key, dont let that confuse you when doing this. – osirisgothra Nov 23 '13 at 10:09
  • @pate: You undo this like you undo anything else, with `u`. – sth Mar 07 '14 at 14:54
  • @sth, I mean: what is the inverse operation of prepending a block? I subsequently discovered `Shift+X`. – Petrus Theron Mar 07 '14 at 15:41
  • If you are used to using Ctrl-C to exit Insert mode, make sure you use Esc instead for this. Otherwise it doesn't work. – Gavin Smith Mar 14 '14 at 20:16
44

To answer your first question, the below

:%s/foo/bar(&)/g

will look for foo, and surround the matched pattern with bar(). The /g will do this multiple times in one line.

Since you're just matching foo, you could do a simple :s/foo/bar(foo)/g. The above will work, however, if you decide to match on a regular expression rather than a simple word (e.g. f[a-z][a-z]). The '&' in the above represents what you've matched.

Brian Agnew
  • 254,044
  • 36
  • 316
  • 423
  • I had a big long answer with macros. This is way easier :-) – Brian Ramsay Jul 23 '09 at 20:33
  • How do you do it for multiple lines? A practical case is when you have a block of code consisted of similar lines which require this substitution. –  Jul 23 '09 at 21:11
  • It sure looks like it works across all lines... note the :%s and /g. – ojrac Jul 23 '09 at 21:15
  • what is interesting is that :%s/foo/bar(&)/gc doesn't confirm -- 'c' has no effect..Ugh –  Jul 23 '09 at 21:18
  • @orjac / @Sasha - my mistake (or misinterpretation). The above will work for all lines - not just the current. – Brian Agnew Jul 23 '09 at 21:29
  • @Sasha - so the above will work for your multiple line scenario – Brian Agnew Jul 23 '09 at 21:30
  • @Sasha - I've just run the above on Vim 7.0 (not 7.2, admittedly) and the /gc *does* force a confirmation message. I don't believe there's anything in the regexp that would disable a confirmation... – Brian Agnew Jul 23 '09 at 21:32
  • 1
    The text between the `:` and the `s` determines which lines it operates on. Nothing means just the current line. `1,30` means lines 1 to 30 (inclusive). `'` means the lines in the current visual selection. – rampion Jul 24 '09 at 01:12
18

To prefix a set of lines I use one of two different approaches:

One approach is the block select (mentioned by sth). In general, you can select a rectangular region with ctrl-V followed by cursor-movement. Once you've highlighted a rectangle, pressing shift-I will insert characters on the left side of the rectangle, or shift-A will append them on the right side of the rectangle. So you can use this technique to make a rectangle that includes the left-most column of the lines you want to prefix, hit shift-I, type the prefix, and then hit escape.

The other approach is to use a substitution (as mentioned by Brian Agnew). Brian's substitution will affect the entire file (the % in the command means "all lines"). To affect just a few lines the easiest approach is to hit shift-V (which enables visual-line mode) while on the first/last line, and then move to the last/first line. Then type:

:s/^/YOUR PREFIX/

The ^ is a regex (in this case, the beginning of the line). By typing this in visual line mode you'll see '<,'> inserted before the s automatically. This means the range of the substitution will be the visual selection.

Extra tip: if your prefix contains slashes, you can either escape them with backslash, or you can use a different punctuation character as the separator in the command. For example, to add C++ line comments, I usually write:

:s:^:// :

For adding a suffix the substitution approach is generally easier unless all of your lines are exactly the same length. Just use $ for the pattern instead of ^ and your string will be appended instead of pre-pended.

If you want to add a prefix and a suffix simultaneously, you can do something like this:

:s/.*/PREFIX & SUFFIX/

The .* matches the whole line. The & in the replacement puts the matched text (the whole line) back, but now it'll have your prefix and suffix added.

BTW: when commenting out code you'll probably want to uncomment it later. You can use visual-block (ctrl-V) to select the slashes and then hit d to delete them, or you can use a substitution (probably with a visual line selection, made with shift-V) to remove the leading slashes like this:

:s:// ::
Hulk1991
  • 2,557
  • 11
  • 29
  • 44
Laurence Gonsalves
  • 125,464
  • 31
  • 220
  • 273
6

:normal to the rescue!

:%norm Wibar(

:%norm WEa)

:norm(al) replays the commands as if you had typed them:

W - goes to the next word

i - starts insertion mode

bar( - types the sequence 'bar('

Or in one line:

:%norm Wibar(ctrlvESCEa)

If you're running Windows then type ctrlq instead of ctrlv.

Community
  • 1
  • 1
Cyber Oliveira
  • 6,959
  • 3
  • 25
  • 18
3

Yet another possibility (probably not-so-useful in your test case, but handy in other situations) is to cordon off the area you want to change with marks.

  • Put the cursor anywhere in the top line and press 'a
  • Put the cursor anywhere in the last line and press 'b
  • Issue the command :'a,'b s/foo/bar(&)/

I usually like visual block mode if everything is visible on the screen, and I usually prefer marks if the start and stop are separated by many screens.

mrk
  • 4,904
  • 3
  • 24
  • 41
  • It should be `m` instead of `'` to set a new marker. `'` is for jumping to the line of an existing marker. `\`` jumps to the line and column of that marker. – tiktak Feb 27 '18 at 00:16
1

Another simple regular expression is:

%s/^/<text you want to prepend>/
Artorias2718
  • 503
  • 5
  • 10
0

For the C-style comments, use the regexp answer by Brian, and match on line ending $, and insert away.

maxwellb
  • 11,744
  • 2
  • 21
  • 33