Vim 搜索并替换选定的文本

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

81882 次浏览

我不认为你可以做到这一点的盒子。但是很多人喜欢这个特性,所以有很多宏之类的东西(我自己添加的)。例如,您可以添加 这里; 只需按 *就可以在视觉选择的文本上搜索下一个匹配项。

尝试执行以下命令或将其输入到 .vimrc

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

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

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

我的 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 ()返回它没有问题,但是我不确定如何正确地将它放到命令行中。如果有人对我如何做到这一点有任何建议,请评论。

米科拉 · 戈卢比耶夫, 谢谢你的提醒!下面使用的“ +”寄存器(取决于您的终端)已经包含突出显示的文本,避免使用“ h”寄存器。

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

接受的答案工程伟大,除非你有特殊的字符在您的视觉选择。我拼凑了两个脚本(Jeremy Cantrell的张贴在这里和 彼得 · 奥丁的) ,使一个命令,让您可视化选择一个字符串,您想要找到,即使它有特殊的正则表达式字符。

" 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中了。

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

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

:'<,'>

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

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

要在以前选择的块上重复 Ex 命令,请使用: history。也就是说,按: then,然后编辑先前的命令。

我最喜欢的简短版本是

Vnoremap s/y: s/”/

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

这个快速而简单的映射搜索视觉上突出显示的文本(没有重写 h 寄存器) ,也没有使用终端依赖 + 寄存器:

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

如果您不喜欢 ctrl-f,请将其更改为您的首选项

一旦文本被突出显示,你总是可以通过简单地输入:

%s//<your-replacement-string>

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

这个方法也可以(至少对于单行/不包含任何特殊字符的选择)

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

0是美国佬的寄存器。

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

//edit: 我刚刚意识到,如果在选择中有像制表符、换行符或 /字符这样的字符,“ register”方法就会失败(我必须以某种方式手动处理这些字符,以便 :s命令能够正常工作) :

enter image description here

我没有代表来评论,所以我要补充另一个答案..。

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

@ dmd 和@dotancohen: 这对我很有用,但是没有用完 "h(显式地使用0,这是最后一个 yank 位置) ,并且可以使用 putty ssh-> 径薄荷(lmde) ; 不知道关于 cent。还使用@Niloct 和@Nathan Friend 评论删除确认。

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

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

维姆卡斯特的一集显示了这个特性。

示例1。用星号引用选定内容,将光标保持在选定内容的开始位置。

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

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

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

解释:

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

解释:

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

其他的答案是好的,但是他们不能逃避特殊的字符。@ brianKennedy 的 回答显示了一个转义方法,但它需要很多代码。例如,对于 URL,转义是强制性的,否则搜索将在“ :”处停止。

正如在 Vim.fandom.com/wiki/search_for_visually_selected_text中编写的,您可以执行一行程序来搜索和转义某些字符。你可以逃避你想要的字符,我选择了逃避 /\::

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

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

我希望在 Vim 中有一种内置的方式来替换一个单词,而不必在第一时间重新打出这个单词。有,虽然它只能对文本工作到一个单词边界字符。

鼠标滑过单词后,按 *#突出显示单词并跳转到单词的下一个/上一个位置(如果你不想改变文件中的位置,那么按相反的键返回到你刚才所在的位置)。

然后打字:

%s//<your-replacement-string>

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

最后,它只有六个或七个键击 + 长度的替换字执行这一点,它不需要宏或编辑您的 .vimrc

下面是米科拉答案的一个变体。我喜欢从当前行开始替换到文本的末尾,然后从开始到当前行(实际上循环从当前行开始而不是从开始)。

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

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