Vim search and replace selected text

Vim

Vim Problem Overview


Let's say we have a text, and I enter visual mode and select some text. How do I quickly do a search for the highlighted text and replace it with something else?

Vim Solutions


Solution 1 - Vim

Try execute the following or put in into your .vimrc

vnoremap <C-r> "hy:%s/<C-r>h//gc<left><left><left>

By pressing ctrl+r in visual mode, you will be prompted to enter text to replace with. Press enter and then confirm each change you agree with y or decline with n.

This command will override your register h so you can choose other one (by changing h in the command above to another lower case letter) that you don't use.

Solution 2 - Vim

This quick and simple mapping search for visually highlighted text (without over-writing the h register) and without using the terminal dependant + register:

" search for visually hightlighted text
vnoremap <c-f> y<ESC>/<c-r>"<CR>   

If you dont like the ctrl-f change it to your preference

Once the text is highlighted you can always do a substitution simply by typing:

%s//<your-replacement-string>

... because a blank search on the s command uses the last searched for string.

Solution 3 - Vim

This one works also (at least for selections in a single line / selections that don't contain any special characters)

  • select the text in visual mode
  • yank the text with y
  • :s/<C-r>0/

0 is the yank register.

As other people mentioned, there are faster ways to do this, but if you've just started learning Vim (like me), this is one of the 'generic' ways.

//edit: I've just realized that the 'register' approach will fail if there are characters like tabs or newlines or / characters in the selection (I'd have to manually process those characters somehow in order for the :s command to work):

enter image description here

Solution 4 - Vim

The accepted answer works great unless you have special characters in your visual selection. I hacked together two scripts (Jeremy Cantrell's posted here & Peter Odding's) to make a command that will allow you to visual select a string that you want to find even if it has special regex characters in it.

" Escape special characters in a string for exact matching.
" This is useful to copying strings from the file to the search tool
" Based on this - http://peterodding.com/code/vim/profile/autoload/xolox/escape.vim
function! EscapeString (string)
  let string=a:string
  " Escape regex characters
  let string = escape(string, '^$.*\/~[]')
  " Escape the line endings
  let string = substitute(string, '\n', '\\n', 'g')
  return string
endfunction

" Get the current visual block for search and replaces
" This function passed the visual block through a string escape function
" Based on this - https://stackoverflow.com/questions/676600/vim-replace-selected-text/677918#677918
function! GetVisual() range
  " Save the current register and clipboard
  let reg_save = getreg('"')
  let regtype_save = getregtype('"')
  let cb_save = &clipboard
  set clipboard&

  " Put the current visual selection in the " register
  normal! ""gvy
  let selection = getreg('"')

  " Put the saved registers and clipboards back
  call setreg('"', reg_save, regtype_save)
  let &clipboard = cb_save

  "Escape any special characters in the selection
  let escaped_selection = EscapeString(selection)

  return escaped_selection
endfunction

" Start the find and replace command across the entire file
vmap <leader>z <Esc>:%s/<c-r>=GetVisual()<cr>/

I've included this in my vimrc if that's more useful to anyone.

Solution 5 - Vim

From Vim 7.4, you can use the gn motion which selects regions of text that match the current search pattern.

After using cgn to change the text in currently selected match (or dgn to delete), in normal mode, you can use . to repeat the command and operate on the next match.

There's an episode of Vimcast showing this feature.

Solution 6 - Vim

From http://vim.wikia.com/wiki/Search_and_replace_in_a_visual_selection:

When text is visually selected, press : to enter a command. The command line will automatically enter the range:

:'<,'>

You can enter a command such as s/red/green/g to replace each red with green in all lines of the last visual selection. The command will appear as:

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

To repeat an Ex command over a previously selected block, use the : history. That is, press : then , then edit a previous command.

Solution 7 - Vim

Mykola Golubyev, Thanks for the tip! Following uses the "+" register which (depending on your terminal) already contains the highlighted text, saving from using the "h" register.

vnoremap <C-r> <Esc>:%s/<C-r>+//gc<left><left><left>

Solution 8 - Vim

I have this in my vimrc:

function! GetVisual() range
    let reg_save = getreg('"')
    let regtype_save = getregtype('"')
    let cb_save = &clipboard
    set clipboard&
    normal! ""gvy
    let selection = getreg('"')
    call setreg('"', reg_save, regtype_save)
    let &clipboard = cb_save
    return selection
endfunction

vmap <leader>z :%s/<c-r>=GetVisual()<cr>/

This will grab the visual selection and start a substitution command with it.

EDIT: I should point out that this does not work with multiline visual selections. While GetVisual() doesn't have a problem returning it, I'm not sure how to properly put it into the command line. If anyone has any tips on how I might do this, please comment.

Solution 9 - Vim

Other answers are good but they do not escape special characters. The answer of @brian kennedy shows a method to escape but it requires much code. In case of an URL for instance, escaping is mandatory or the search will stop on “:”.

As written in vim.fandom.com/wiki/Search_for_visually_selected_text, you can do a oneliner to search and escape some characters. You can escape the characters you want, I chose to escape /\: :

vnoremap // y/\V<C-R>=escape(@",'/\:')<CR><CR>

With this map, I must press // in visual mode to search the currently selected text on the whole buffer.

Solution 10 - Vim

I was hoping there was a built in way in Vim to replace a word, without having to retype the word out in the first place. There is, although it will only work for text up to a word boundary character.

Once you've moused over the word, press * or # to highlight the word and jump to the next/previous location of it (if you don't want to change locations in the file, then press the opposite key to go back to the location you were just at).

Then just type:

%s//<your-replacement-string>

As mentioned in another person's answer, if %s receives a blank entry between the slashes, then it uses the previously searched for word. By pressing * or #, you're searching for the word under the cursor which makes it the most recently searched word.

In the end it's only six or seven keystrokes + length of replacement word to perform this and it requires no macro or editing of your .vimrc.

Solution 11 - Vim

I don't think you can do this out of the box. But lots of people like this feature, so there's tons of macros and such (I've added it myself). Here is one you can add, for example; just press * to search for the next match on the visually selected text.

Solution 12 - Vim

My favorite short version of this is

vnoremap s/ y:s/"/

Then you can highlight a selection and just hit s/ to start a substitution command for it.

Solution 13 - Vim

I don't have the rep to comment, so I'm adding yet another answer...

vnoremap <C-r> "0y<Esc>:%s/<C-r>0//g<left><left>

@dmd and @dotancohen: this worked for me without using up "h (explicitly uses 0, which is the last yank position anyway) and works with putty ssh -> mint (lmde); don't know about cent. Also uses @Niloct and @Nathan Friend comments to remove confirmation.

Solution 14 - Vim

Example 1. Quote selection with stars, keep cursor at start of selection.

:%s,\%#\%V\_.*\%V/,**&**,c 

Example 2. Pipe selected text with base64:

:%s!\%#\%V\_.*\%V!\=system("base64 -w 0",@")!c

Explanation LHS:

\%# matches cursor 
\%V matches inside the selection only
\_. matches any character.
\_.* matches beginning to end of selection.

Explanation RHS:

\=expr()  Replace match with result of expr() for each substitution.

Solution 15 - Vim

Here is a variation on Mykola's answer. I like making substitutions starting from the current line to the end of the text, then from the beginning to the current line (essentially the loop starts from the current line instead of the beginning).

vnoremap <C-r> "hy:.,$s/<C-r>h//gc \|1,.&& <left><left><left><left><left><left><left><left><left><left><left>

First, the substitution is made from the current line to the end of the text .,$, then it is repeated from the beginning to the current line \|1,.&&. The 11 <left> put the cursor in the right place.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGabriel SolomonView Question on Stackoverflow
Solution 1 - VimMykola GolubyevView Answer on Stackoverflow
Solution 2 - VimErichBSchulzView Answer on Stackoverflow
Solution 3 - VimcolemikView Answer on Stackoverflow
Solution 4 - Vimbryan kennedyView Answer on Stackoverflow
Solution 5 - VimDapeng LiView Answer on Stackoverflow
Solution 6 - VimsyvexView Answer on Stackoverflow
Solution 7 - VimdmdView Answer on Stackoverflow
Solution 8 - VimJeremy CantrellView Answer on Stackoverflow
Solution 9 - VimRomainTTView Answer on Stackoverflow
Solution 10 - VimCameron GagnonView Answer on Stackoverflow
Solution 11 - VimJohn FeminellaView Answer on Stackoverflow
Solution 12 - VimalexView Answer on Stackoverflow
Solution 13 - Vim10'004View Answer on Stackoverflow
Solution 14 - VimmoshView Answer on Stackoverflow
Solution 15 - VimGuillaume St-OngeView Answer on Stackoverflow