Vim搜索并替换所选文本

时间:2009-03-24 09:02:21

标签: vim

假设我们有一个文本,然后进入可视模式并选择一些文本。如何快速搜索突出显示的文本并将其替换为其他内容?

15 个答案:

答案 0 :(得分:116)

尝试执行以下操作或将其放入.vimrc

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

在可视模式下按 ctrl + r ,系统将提示您输入要替换的文本。按输入,然后确认您同意 y 的每个更改,或使用 n 拒绝。

此命令将覆盖您的注册h,以便您可以选择其他一个(通过将上面命令中的h更改为另一个小写字母),而不使用。

答案 1 :(得分:31)

快速简单地映射搜索视觉突出显示的文本(不覆盖h寄存器)并且不使用依赖于终端的+寄存器:

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

如果您不喜欢ctrl-f,请将其更改为您的偏好

文字突出显示后,您只需键入以下内容即可s ubstitution:

%s//<your-replacement-string>

...因为s命令的空白搜索使用最后搜索的字符串。

答案 2 :(得分:22)

除非您的视觉选择中有特殊字符,否则接受的答案效果很好。我把两个脚本(Jeremy Cantrell发布在这里&amp; Peter Odding)一起攻击,制作一个命令,允许你直观地选择你想要找到的字符串,即使它有特殊的正则表达式字符在它。

" 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>/

如果这对任何人都有用,我已将其包含在vimrc中。

答案 3 :(得分:17)

这个也适用(至少对于一行中的选择/不包含任何特殊字符的选择)

  • 以可视模式选择文字
  • 使用y
  • 抽取文字
  • :s/<C-r>0/

0是一个猛烈的注册。

正如其他人提到的那样,有更快的方法可以做到这一点,但如果你刚开始学习Vim(就像我一样),这就是'通用'方式之一。

//编辑:我刚刚意识到,如果选项中有标签或换行符或/字符等字符,那么“注册”方法将会失败(我必须以某种方式手动处理这些字符)命令:s命令工作):

enter image description here

答案 4 :(得分:8)

来自http://vim.wikia.com/wiki/Search_and_replace_in_a_visual_selection

视觉选择文本时,按:输入命令。命令行将自动进入范围:

:'<,'>

您可以输入一个命令,例如s / red / green / g,在最后一个视觉选择的所有行中用绿色替换每个红色。该命令将显示为:

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

要对先前选定的块重复Ex命令,请使用:history。也就是说,按:然后编辑上一个命令。

答案 5 :(得分:6)

Mykola Golubyev, 谢谢你的提示!以下使用“+”寄存器(取决于您的终端)已包含突出显示的文本,使用“h”寄存器进行保存。

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

答案 6 :(得分:5)

从Vim 7.4开始,您可以使用gn动作选择与当前搜索模式匹配的文本区域。

使用cgn更改当前所选匹配项中的文本(或dgn删除)后,在正常模式下,您可以使用.重复命令并对下一个操作进行操作匹配。

an episode of Vimcast显示此功能。

答案 7 :(得分:4)

我在我的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>/

这将抓取视觉选择并用它开始替换命令。

编辑:我应该指出,这不适用于多行视觉选择。虽然GetVisual()没有返回它的问题,但我不确定如何正确地将它放入命令行。如果有人对我如何做到这一点有任何提示,请发表评论。

答案 8 :(得分:3)

其他答案很好,但是它们不能转义特殊字符。 @brian kennedy的answer显示了一种转义方法,但需要大量代码。例如,如果使用URL,则必须进行转义,否则搜索将在“:”处停止。

vim.fandom.com/wiki/Search_for_visually_selected_text所述,您可以做一个内衬来搜索和转义一些字符。您可以转义想要的字符,我选择转义/\:

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

在这张地图上,我必须在可视模式下按//才能在整个缓冲区中搜索当前选择的文本。

答案 9 :(得分:1)

我认为你无法开箱即用。但是很多人喜欢这个功能,所以有很多宏等等(我自己添加了它)。例如,您可以添加Here;只需按*即可在视觉选择的文字上搜索下一个匹配项。

答案 10 :(得分:1)

这是 Mykola 答案的一个变体。我喜欢从当前行开始替换到文本的结尾,然后从开头到当前行(本质上循环从当前行而不是开头开始)。

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

首先从当前行到文本.,$的末尾进行替换,然后从开始到当前行\|1,.&&重复。 11 <left> 将光标放在正确的位置。

答案 11 :(得分:0)

我最喜欢的简短版本是

vnoremap s / y:s /“/

然后你可以突出显示一个选择,然后点击s /为它启动一个替换命令。

答案 12 :(得分:0)

我没有代表发表评论,所以我又添加了另一个答案...

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

@dmd和@dotancohen:这对我有用而不用"h(显然使用0,这是最后一个猛拉位置)并且使用putty ssh - &gt;薄荷(lmde);不知道分钱。还使用@Niloct和@Nathan Friend评论删除确认。

答案 13 :(得分:0)

示例1.使用星号进行引号选择,将光标保持在选择的开始位置。

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

示例2.使用base64管道选定的文本:

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

解释LHS:

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

解释RHS:

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

答案 14 :(得分:0)

我希望Vim中有一个内置的方式来替换单词,而不必首先重新输入单词。有,尽管它仅适用于不超过单词边界字符的文本。

将鼠标悬停在单词上后,按*#突出显示单词,然后跳至单词的下一个/上一个位置(如果您不想更改单词中的位置文件,然后按相反的键返回到您所在的位置。

然后只需键入:

%s//<your-replacement-string>

如另一个人的答案中所述,如果%s在斜杠之间接收到空白条目,则它将使用之前搜索的单词。通过按*#,您正在光标下搜索单词,这使其成为最近搜索到的单词。

最后,只需执行六到七次击键操作+替换单词的长度即可,并且不需要宏或编辑.vimrc