Vi and Vim Stack Exchange is a question and answer site for people using the vi and Vim families of text editors. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top
This is a sample sentence.
This is a second sample sentence.

Let's say I select 'is a' of the first sentence. Now I want to change all occurrences of what is selected (including the selection itself) to 'is not a'. How do I do that?

share|improve this question
4  
(by learning Vim. "This is a simple question") :) E.g if you visually selected "is a", now you do y to yank it, then: :%s/ Ctrl-r " /is not a/g to substitute with is not a. Ctrl-r " will paste is a from the default register into the substitute command. – VanLaser Feb 26 at 15:07
1  
@le0m You want a mapping in visual mode which replaces the visual selection with an arbitrary string ? If so you could try this: xnoremap ,s y:<C-U>let replacement = input('Enter replacement string: ') <bar> %s/<C-R>"/\=replacement/g<CR> (Here the mapping is ,s but you could change it to what you want). – saginaw Feb 26 at 15:13

You could execute the following command: :%s/is a/is not a :

  • Select and yank is a with your favorite method (visual selection and y, y2w with cursor on is, etc...)
  • Enter command mode with :
  • Begin to write your replacement command %s/
  • Insert the text to replace with Ctrl+r and ". (see Note2)
  • Finish to write the replacement command /is not a
  • Execute the replacement command with Enter

Note if you have several occurrences of is a on same line use the g tag to substitute all occurrences of a same line: :%s/is a/is not a/g

Note 2 When you are in insert mode Ctrl+r allows you to choose a register and to insert its content. When you yanked your text in the first step you yanked it to the unnamed register which is accessible with ". So when you type Ctrl+r followed by " you're inserting the text you yanked before.

See :h i_CTRL-R and :h registers as advised by @VanLaser for more details about registers.

See :h :s for more informations about the search and replace function.

Edit I had not seen the comment of @VanLaser who basically gave the same solution, sorry.

share|improve this answer
    
(no problem from my part) :) – VanLaser Feb 26 at 15:19
1  
@VanLaser it's cool then =) – statox Feb 26 at 15:20
    
Thanks for the answer! I did know about :%s from the tut file. But the bit with ctrl+r and " remains a mystery :-\ How do I get info out of :h about it? – le0m Feb 26 at 15:27
2  
:h c_CTRL-R (c_ comes from command-line mode, CTRL-R is the way you specify a combo when using help). See also :h i_CTRL-R (for the similar operation in insert mode), and :h registers to see what's up with ". – VanLaser Feb 26 at 15:31

Using gn and . for quick replacements

You can use gn motion to make replacing matches quicker. Simply search for your text

/foo

Then change the current match with the change operator, c, and the gn motion.

cgnbar<esc>

Simply repeat this via the . command as many times as you wish. You can also use n to jump to the next match in case you want to skip any matches.

There is a nice Vimcasts episode on this topic: Operating on search matches using gn

For more help see:

:h gn
:h /
:h .
:h n

Aside: Tips on searching for selected text

Vim's help doc provides the following mapping under :h visual-search:

:vmap X y/<C-R>"<CR>

This is better than searching by hand however it does not take escaping into consideration and causes the side effect of overwriting the unnamed register. Some of this can be mitigated by using \V to turn on "very 'nomagic'".

Personally I would get a visual star plugin (there are few out there). There is a nice Vimcast about this: Search for the selected text. This means you can select the line visually and then press *.

If a plugin isn't your thing you can add the following mapping to your vimrc to mimic a visual star plugin:

xnoremap * :<c-u>let @/=@"<cr>gvy:let [@/,@"]=[@",@/]<cr>/\V<c-r>=substitute(escape(@/,'/\'),'\n','\\n','g')<cr><cr>

Note: The mapping above will not work for visual-block mode.

For more help see:

:h visual-search
:h c_CTRL-R
:h /\V
:h /magic
share|improve this answer
    
Great answer, +1 ! With a mutiline pattern, I think the last mapping wouldn't work as expected. For example, if you have a buffer containing several groups of 2 consecutive lines foo and bar, you select one of them and copy it with y, and type /<C-R>", instead of searching for foo\nbar\n, you will search for foo^Mbar^M, because Vim will automatically interpret \n as a literal carriage return whose caret notation is ^M. At least, it seems to happen on my machine, maybe I have some wrong settings though. – saginaw Feb 26 at 18:47
    
Maybe, the solution would be to protect the newline by replacing all \n with \\n: xnoremap * :<c-u>let @/=@"<cr>gvy:let [@/,@"]=[@",@/]<cr>/\V<c-r>=substitute(escape(@/,'\/'),'\n','\\n','g')<cr><cr> – saginaw Feb 26 at 18:47
    
@saginaw I have tested and changed the mapping. Good catch. – Peter Rincker Feb 26 at 18:57

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.