Vim搜索并替换所选文本

Gab*_*mon 102 vim

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

Myk*_*yev 127

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

vnoremap <C-r> "hy:%s/<C-r>h//gc<left><left><left>
Run Code Online (Sandbox Code Playgroud)

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

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

  • 如果省略`gc`中的`c`,则在整个缓冲区中立即执行replace.如果你犯了一个错误并想要恢复它,只需在命令模式下键入`u`即可.我更喜欢这种方法,而不是确认每一个替换(使用`c`修饰符). (12认同)
  • `<left> <left> <left>`的目标是什么? (7认同)
  • @aymericbeaumet获取两个正斜杠之间的光标,这样可以轻松输入替换单词. (6认同)
  • 请注意,如果你接受@ Niloct关于从`gc`中删除`c`的建议,你还必须从行的末尾删除一个`<left>`. (4认同)
  • `vmap*y:让@/= @"<CR>`选中突出显示. (3认同)

Eri*_*ulz 33

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

" search for visually hightlighted text
vnoremap <c-f> y<ESC>/<c-r>"<CR>   
Run Code Online (Sandbox Code Playgroud)

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

一旦文本突出显示,您s只需输入以下内容即可完成ubstitution:

%s//<your-replacement-string>
Run Code Online (Sandbox Code Playgroud)

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


bry*_*edy 22

除非您的视觉选择中有特殊字符,否则接受的答案效果很好.我把两个脚本(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 - 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>/
Run Code Online (Sandbox Code Playgroud)

我把它包含在我的vimrc中,如果这对任何人都更有用.

  • 感谢您的解决方案,结合多个建议,我最终得到以下结果:`vmap &lt;Cr&gt; &lt;Esc&gt;:%s/&lt;cr&gt;=GetVisual()&lt;cr&gt;//g&lt;left&gt;&lt;left&gt;`(这只是替换文件中的所有内容) (2认同)

col*_*mik 20

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

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

0 是一个猛烈的注册.

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

//编辑:我刚刚意识到如果在选择中有像标签或换行符或/字符这样的字符,那么"注册"方法将会失败(我必须以某种方式手动处理这些字符才能使:s命令工作):

在此输入图像描述

  • 对于我们这些仍处于 Vim 学习曲线早期的人来说,这是理想的答案。我知道定制是一种优势,但我不想将复杂的脚本复制粘贴到我的 vimrc 中,并困惑如何将其组合在一起解决如此简单的问题。这个答案告诉我 ctrl-R 转储一个寄存器,这在其他上下文中会很容易记住。 (4认同)
  • 这很简单。天哪,为什么维基百科上没有介绍它。拜托...谢谢你的回答! (2认同)
  • 关于您上次对特殊字符的编辑(我在路径中有斜杠 /),您可以简单地使用其他分隔符(例如 * 或 |,哪个更适合您)。这样,我使用星号 * 作为分隔符,使用类似 ```:%s*&lt;Cr&gt;0*/Users/very/long/path/here/*gc``` 的命令替换了整个文件中的复杂路径 (2认同)

Dap*_* Li 8

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

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

一集Vimcast显示这个功能.

  • 这是一个很好的答案! (2认同)

Cam*_*non 8

我希望 Vim 中有一种内置方法可以替换单词,而不必首先重新输入单词。有,但它仅适用于不超过单词边界字符的文本。

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

然后只需输入:

%s//<your-replacement-string>

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

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


小智 6

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

vnoremap <C-r> <Esc>:%s/<C-r>+//gc<left><left><left>
Run Code Online (Sandbox Code Playgroud)

  • 我注意到我通过Putty访问CentOS机器,在谷歌搜索时我看到+是剪贴板寄存器.Putty似乎不支持这个!所以这个答案实际上是终端依赖的. (3认同)

syv*_*vex 6

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

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

:'<,'>
Run Code Online (Sandbox Code Playgroud)

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

:'<,'>s/red/green/g
Run Code Online (Sandbox Code Playgroud)

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

  • 一个很好的提示,但没有解决指定的需求. (9认同)
  • 是的,这将在所选区域中用红色*替换红色* - 非常有用,但不是op所要求的. (2认同)
  • 也许它没有回答OP问题,但这确实回答了我的搜索“vim搜索并替换为视觉选择”,我想将搜索和替换限制为仅视觉选择,这提出了这个问题 (2认同)

Jer*_*ell 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>/
Run Code Online (Sandbox Code Playgroud)

这将获取视觉选择并使用它启动替换命令。

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