Vim搜索并替换所选文本


109

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

Answers:


135

尝试执行以下或放入您的 .vimrc

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

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

该命令将覆盖您的寄存器,h因此您可以选择不使用的其他寄存器(通过h在上面的命令中将其更改为另一个小写字母)。


13
如果省略cin gc,则立即在整个缓冲区中进行替换。如果您犯了一个错误并且想要恢复它,只需u在命令模式下输入即可。与确认每个替换项(使用c修饰符)相比,我更喜欢这种方法。
Niloct 2011年

3
vmap * y:let @/ = @"<CR>选中突出显示。
千电子伏

8
目的是<left><left><left>什么?
aymericbeaumet

7
@aymericbeaumet可使光标位于两个正斜杠之间,这样可以轻松键入替换单词。
mcabrams

5
请注意,如果您采用@Niloct关于c从中删除的建议gc,则还必须<left>从行尾删除之一。
弥敦道(Nathan Friend)

36

这种快速,简单的映射搜索可视化突出显示的文本(不覆盖h寄存器),而无需使用依赖于终端的+寄存器:

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

如果您不喜欢ctrl -f,请根据自己的喜好进行更改

文本突出显示后,您始终可以s通过输入以下内容来进行简单处理:

%s//<your-replacement-string>

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


当我在vim配置中使用它时,control+f总是选择下一个字符以及我在视觉上选择的字符。有任何想法吗?
罗伯特·马克·布拉姆

%s//<your-replacement-string>似乎无法突出显示诸如/tmp/file。它变成了<your-replacement-string>/tmp/file
naisanza

28

此功能也适用(至少适用于单行中的选择/不包含任何特殊字符的选择)

  • 在可视模式下选择文本
  • y
  • :s/<C-r>0/

0 是猛拉寄存器。

正如其他人所提到的,有更快的方法可以执行此操作,但是,如果您刚开始学习Vim(像我一样),则这是“通用”方法之一。

// edit:我刚刚意识到,如果有诸如制表符或换行符之类的/字符或所选内容中的字符,“注册”方法将失败(我必须以某种方式手动处理这些字符,才能使:s命令起作用):

在此处输入图片说明


2
非常简单 噢,天哪,为什么它不在Wiki上介绍。来...谢谢您的回答!
Benyamin Limanto

2
对于那些仍然处于Vim学习曲线早期的人来说,这是一个理想的答案。我知道定制是一种优势,但是我不想将复杂的脚本复制粘贴到我的vimrc中,并想办法解决如何将其简单地解决这个问题。这个答案告诉我ctrl-R转储寄存器,在其他情况下方便记住。
nivek

26

除非您在视觉选择中包含特殊字符,否则可接受的答案非常有用。我将两个脚本(Jeremy Cantrell的发布和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 - /programming/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中


2
感谢您的解决方案,结合了多个建议,我得到了以下内容:(vmap <C-r> <Esc>:%s/<c-r>=GetVisual()<cr>//g<left><left>仅替换了所有内容)
Peter Butkovic

13

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

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

Vimcast一集显示了此功能。


3
这是一个很好的答案!
mauriciojost

这也很棒。除了colemik的答案。太好了!
Benyamin Limanto

哇,这就像您深入浏览以找到一个好的解决方案时发现的秘密之一,谢谢!
vdegenne

8

Mykola Golubyev,谢谢!以下使用“ +”寄存器(取决于您的终端)已经包含突出显示的文本,从而避免使用“ h”寄存器。

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

我在CentOS 5.x上的VIM 7.0似乎没有+寄存器。这是标准功能吗?
dotancohen 2012年

3
我注意到我通过Putty访问CentOS机器,并且在谷歌搜索后看到+是剪贴板寄存器。腻子似乎不支持这一点!因此,这个答案实际上取决于终端。
dotancohen 2012年

嗨,我尝试了您的命令,但它要求我替换整个文件中指定文本的出现,而不仅仅是所选文本
solalito 2015年

7

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

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

:'<,'>

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

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

要在先前选择的块上重复执行Ex命令,请使用:历史记录。也就是说,按:,然后按,然后编辑上一个命令。


4
是的,这在选定区域将红色替换为绿色-非常有用,但不是操作员要求的内容。
ErichBSchulz

@ErichBSchulz实际上在所有选定的行上都执行此操作。因此,即使只选择了一部分线,它也会对整个线进行选择。
Cully 2014年

1
也许它不能回答OP问题,但这确实可以回答我的搜索“ vim搜索并替换为视觉选择”,在这里我想将搜索和替换仅限于视觉选择,这带来了这个问题
icc97

5

我的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()返回它没有问题,但我不确定如何正确地将其放入命令行。如果有人对我的操作方法有任何建议,请发表评论。


2

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


2

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

vim.fandom.com/wiki/Search_for_visually_selected_text所写,您可以执行一个单行代码来搜索和转义某些字符。您可以转义想要的字符,我选择转义/\: :

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

使用此映射,我必须按//可视模式在整个缓冲区中搜索当前选定的文本。


1

我最喜欢的短版是

vnoremap s / y:s /“ /

然后,您可以突出显示一个选择,只需按s /即可启动替换命令。


对我没用,被"当作字面意思。<c-r>"尽管工作了
乔什·波达

1

我没有代表对此做评论,所以我要添加另一个答案...

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

@dmd和@dotancohen:这对我有用而没有用完"h(无论如何,显式地使用0,这是最后一个拉线位置),并与腻子ssh-> mint(lmde)一起工作;不知道分。还使用@Niloct和@Nathan Friend注释删除确认。


1

示例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.

0

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

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

然后输入:

%s//<your-replacement-string>

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

最后,只需执行六到七次击键,再加上替换单词的长度即可执行此操作,并且不需要宏或进行修改.vimrc

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.