在Vim中,有没有一种方法可以删除而不在寄存器中输入文本?


470

使用Vim,我经常想用我刚刚拉过的代码块替换代码块。

但是,当我删除要替换的代码块时,该代码块本身进入寄存器,该寄存器将擦除我刚刚提取的代码块。因此,我习惯于拉动,然后插入,然后删除我不想要的内容,但是对于大型代码块,尝试将插入的块和要删除的块分开是很麻烦的。

那么,在Vim中替换文字的最流畅最快的方法是什么?

  • 有没有办法删除文本而不将其放入寄存器?
  • 有没有办法说例如“替换下一个单词”或“替换到下一个段落”
  • 还是以某种方式使用多重注册功能的最佳方法?

1
vim-easyclip(github.com/svermeulen/vim-easyclip)旨在解决这个确切的问题
Steve Vermeulen

1
我问了一个问题,在不知不觉中(当时)重复了您的实际问题,但没有标题问题那么多。TL; DR-替换为您使用过的viwp(用于word)。
OJFord

Answers:


429

要删除某些内容而不将其保存在寄存器中,可以使用“黑洞寄存器”:

"_d

当然,您也可以使用其他任何不包含您感兴趣的寄存器的寄存器。


4
起初,我认为该命令无法正常工作。然后我意识到我正在使用美国键盘的“死键”版本。使用这种键盘布局我必须输入"<space>_d。要实际键入“,需要用空格。
SebastiánGrignoli 2012年

4
关于仅在空白行上选择性地执行此操作的任何想法?(如果我dd在空行上,它将进入黑洞,否则dd就像正常情况一样)。
乔纳森·杜马因

6
要删除一个字符,请尝试:"_x
kenorb 2013年

54
这是标准文本编辑器获胜的领域。您只需按Delete键。
文斯·潘努乔

22
您也可以用yy或'3yy'(或其他任何东西)提取内容,将其放入未命名的寄存器中,也可以放入0中。然后"0p,尽管d之后使用过,也可以继续粘贴它。
Halfgaar 2015年

102

是的 与先删除“旧”文本相比,它有些复杂,但是:

我从开始

line1
line2
line3
line4

old1
old2
old3
old4

shift+ v选择第1行,第2、3和4行,并使用以下d命令将其删除

然后我以同样的方式删除旧的1-4行。

然后做

"2p

这将粘贴倒数第二行的线条(第1-4行)。"3p将执行倒数第三,依此类推。

所以我最终

line1
line2
line3
line4

参考: 有关编号寄存器的Vim文档


如果使用<Shift-v>选择行,则仅用d而不是dd删除它们
Heikki Naski 2010年

31
1至9适用于删除。要粘贴过去的事情真的猛拉(与“Y”),你必须使用“0P这就是在你第一次猛拉什么打算更换别的情况下非常有用,但随后其他的东西覆盖默认粘贴寄存器。
拉斐尔德F.费雷拉

欲了解更多撤消复杂退房Gundo(图形撤消)脚本
Lumi 2012年

@ RafaeldeF.Ferreira:您的评论不是对这个问题的答案,但实际上可以解决导致OP首先提出问题的实际问题。对我来说,这是真正的问题。
0xc0de

76

VIM文档:编号为0的寄存器包含来自最新yank命令的文本,除非该命令用[“ x]指定了另一个寄存器。

例如,我们猛拉“ foo”并删除“ bar”-注册表0仍包含“ foo”!因此可以使用以下命令粘贴“ foo”"0p


53

方便地进行映射很方便,该映射使您可以用缓冲区替换当前选择。

例如,当您将其放入.vimrc中时

vmap r "_dP       // it's a capital 'p' on the end

然后,将某些内容复制到寄存器中(即带有“ y”)后,您只需选择要替换的文本,然后在键盘上按“ r”即可。选择内容将替换为您当前的寄存器。

说明:

vmap - mapping for visual mode
"_d - delete current selection into "black hole register"
P - paste

1
有关更高级的版本,请访问:stackoverflow.com/questions/290465/…–
卢克·赫米特

我想使用vmap <C-P> "_dP
哈里·李

7
您可以直接放置文本,而不删除选择。例如,立即Vp将当前行替换为被选中的行。
Bobby Marinoff 2015年

该解决方案无法解决问题,d因为该问题通常用于删除。
维克多·亚雷玛

35

我在vimrc中添加了以下内容:

noremap  y "*y
noremap  Y "*Y
noremap  p "*p
noremap  P "*P
vnoremap y "*y
vnoremap Y "*Y
vnoremap p "*p
vnoremap P "*P

现在,我从剪贴板寄存器移入并移出,而不必关心默认寄存器会发生什么。另一个好处是,我可以轻松地从其他应用程序粘贴。我知道我失去了一些功能,但是无论如何我都无法跟踪多个寄存器/剪贴板。


6
除了所有这些重新映射,您还可以选择set clipboard=unnamedset clipboard=unnamedplus,将默认剪贴板分别更改为*+
史蒂夫·

5
@Steve如果这样做,则d还将覆盖到剪贴板寄存器中的最后一个挽回,这就是该问题试图避免的问题。
79E09796

1
@ 79E09796,我不是要暗示会这样做;我在评论这个答案,而不是原始问题。
史蒂夫·

1
我将它们放在我的.vimrc文件中,现在拉动不起作用。知道为什么吗?
tba

2
@tba用nnoremap(两个n)替换noremap,它应该可以正常工作。

24

对于您给出的特定示例,如果我理解问题,那么这可能会起作用:

*Highlight what you want to put somewhere else
*delete (d)
*Highlight the code that you want it to replace
*paste (p)

6
除非您要粘贴多个选择,否则此方法效果很好。

23

默认情况下,所有拉动和删除操作都会写入未命名的寄存器。但是,最新一次发送和最新删除总是(单独)存储在编号寄存器中。该寄存器0包含最新的yank。寄存器中1-9保存了9个最近的删除(1是最新的)。

换句话说,删除操作会覆盖未命名寄存器中的最新操作,但仍保留在0寄存器中。"_dd其他答案中提到的黑洞寄存器技巧()可以起作用,因为它可以防止覆盖未命名的寄存器,但这不是必需的。

您可以使用双引号引用寄存器,因此可以像这样粘贴最近粘贴的文本:

"0p

这是一个很好的参考:


16

为了强调EBGreen所说的话

如果在选择文本时粘贴,则所选文本将替换为粘贴的文本。

如果要复制一些文本,然后将其粘贴到多个位置,请使用"0p粘贴。编号为0的寄存器包含来自最新yank命令的文本。


另外,您可以列出所有寄存器的内容:

:registers

执行dbr的answer等操作时,使用该命令可以更轻松地确定所需的寄存器。您还将看到/,%,#寄存器。(另请参见:help registers


最后,签出cWcW更改包含和不包含尾随空格的单词。(使用大写W字母包括标点符号。)


10

如果您使用的是Vim,那么您将拥有可视模式,就像选择模式一样,但是使用分离模式是vi / vim的基础。

您要执行的操作是使用可视模式选择源,然后拉动,然后再次使用可视模式选择目标范围,然后从默认缓冲区粘贴到文本。

例:

在带有以下内容的文本文件中:

1 | wer
2 | 自卫队
3 | zxcv
4 | iu

按以下顺序进行:ggVjyGVkp您将以:

1 | wer
2 | 自卫队
3 | ew
4 | 自卫队

解释:

  • gg:转到第一行
  • V:以整行开始可视模式
  • j:向下移动一行(选择从前几行开始,这会使选择向下移动一行)
  • y:拉到默认缓冲区(选中的两行,它会自动从可视模式退出)
  • G:转到最后一行
  • V:启动可视模式(与以前相同)
  • k:向上一行(与以前一样,启用可视模式,这会使选择向上一行)
  • p:粘贴(在最后两行中进行选择,它将用缓冲区中的内容替换这些行,在这种情况下为前两行)

这样做有一点不方便,就是将最后一个块放在缓冲区中,因此以某种方式重复粘贴同一件事是不希望的,因此,您需要将源保存到命名缓冲区中,例如"ay(保存到名为“ a “),并且用类似粘贴"ap(但当时如果你是编程,你可能不想贴几次,但创建一个函数并调用它,对吗?RIGHT?)。

如果您仅使用vi,那么您将不得不使用不可见标记代替可视模式,:he mark对此,我很抱歉,但是我对这种不可见标记的东西不太满意,我对可见模式很感兴趣。



9

懒惰的最小侵入性解决方案:

寄存器0始终包含最后一个键(如Rafaelalex2k8idbrii所述)。不幸的是,一直选择寄存器0非常烦人,因此如果默认p使用它会很好"0。可以通过在您的计算机中添加以下几行来实现.vimrc

noremap p "0p
noremap P "0P
for s:i in ['"','*','+','-','.',':','%','/','=','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
    execute 'noremap "'.s:i.'p "'.s:i.'p'
    execute 'noremap "'.s:i.'P "'.s:i.'P'
endfor

第一行将每个p笔划映射到"0p。但是,这将阻止p访问任何其他寄存器。因此p,具有明确选择的寄存器的所有笔划都将映射到for循环内的等效命令行表达式。的操作相同P

这样,除了隐式pP笔触0(默认情况下现在使用注册)之外,保留了标准行为。

提示1: cut命令现在"0d不再是d。但是由于我很懒,这对我来说太长了;)因此,我正在使用以下映射:

noremap <LEADER>d "0d
noremap <LEADER>D "0D

引导键是\默认设置,因此您可以通过键入\d或轻松剪切文本\D

提示2:多键映射的默认超时时间很短。您可能希望增加它,以便在选择寄存器时有更多时间。有关:help timeoutlen详细信息,请参阅,我正在使用:

set timeout timeoutlen=3000 ttimeoutlen=100

7

好吧,首先执行以下命令:

:h d

然后您将意识到可以删除特定的寄存器。这样,您将不会更改默认寄存器中的内容。


1
["x]d{motion} Delete text that {motion} moves over [into register x]-Vim:h d
Wes Turner

5

我的情况:在Normal模式下,当我使用x按键删除字符时,这些删除会覆盖我最新的寄存器-使要删除字符的编辑变得复杂,x并粘贴我最近寄存器中的内容(例如,将相同的文本粘贴到两个或两个字符上)更多的地方)。

我在接受的答案("_d)中尝试了该建议,但是没有用。

但是,从/vi/122/performing-certain-operations-without-clearing-register处的可接受答案/评论中,我将此添加到了我的~/.vimrc,它可以正常工作(您可能必须重新启动Vim ):

nnoremap x "_x

也就是说,我现在可以执行常规的yank(y),delete(d)和paste(p)命令-并且使用x不再删除的字符不再填充最新的寄存器。


4

在插入模式下删除的文本不会进入默认寄存器。


2
但是在默认模式下删除大量文本是SLOW
Hamish Downer

3

我在正确的环境中使用的两个解决方案是:

  • 高亮显示您要使用Vims VISUAL模式替换的内容,然后粘贴寄存器。

我习惯这种习惯是因为我很晚才找到第二种解决方案,例如

yiw   " yank the whole word
viwp  " replace any word with the default register
  • YankRing。使用此插件,您可以使用键盘绑定<ctrl>+<p>将先前编号的寄存器替换为您刚刚粘贴的寄存器。

基本上,您将按照自己<C-P>的意愿进行粘贴,但是当您意识到自此之后就覆盖了默认寄存器,从而丢失了您实际想要粘贴的内容后,就可以从YankRing历史中查找并替换!

其中之一必须具有插件...



2

在Windows版本中(也可能在Linux中),您可以使用"*y(例如,在yank命令前加上双引号和星号)来提取系统的复制/粘贴缓冲区。

然后,您可以正常删除可替换的行,并使用粘贴复制的文本"*p


2

当我按照命令先'y'ank然后'“ _d'进入黑洞然后'p'aste时,我经常会犯一个错误。我更喜欢'y'ank,然后删除我喜欢的东西,然后从0寄存器,这是最后复制的文本被压入的位置。


2

对于emacs-evil用户,(evil-paste-pop)可以在粘贴后触发该功能,并在kill-ring中的先前条目之间循环。假设你把它绑定到<C-p>(在Spacemacs默认),你会打p,然后尽可能多的<C-p>需要。


1

对于Dvorak用户,一种非常方便的方法是仅将不需要的文本删除到“ 1寄存器”而不是“ _黑洞寄存器”中,如果仅是因为您可以用相同的Shift键和快速的粉红色运动来按“ +1”,因为1是Dvorak中“”正上方的键(另一方面是PLUS d,这使整个命令像地狱一样快)。

然后,当然,“ 1寄存器由于其方便性而可以用于其他用途,但是除非您有一个比替换文本更通用的目的,否则我会说它是寄存器的一个很好的用法。


1

对于那些最主要的兴趣是通过虚拟选择和粘贴替换文本时不覆盖未命名寄存器的人。

您可以使用以下简单且最适合我的解决方案:

xnoremap <expr> p 'pgv"'.v:register.'y'

它来自此处的答案(和评论): 如何粘贴而不覆盖注册

它首先经过选择,然后再次选择带有新文本的选择(gv)。现在,最后一次在可视模式下使用的寄存器(通常是未命名的寄存器,但是如果您使用另一个寄存器进行粘贴也可以避免副作用)。然后将新值再次拉到寄存器中。

PS:如果您需要一个更简单的变量,该变量也可以与intellj idea插件vim模拟一起使用,则可以使用此变量(缺点:即使给了另一个寄存器用于粘贴,也可以覆盖未命名的寄存器):

vnoremap p pgvy



0

Vim偶尔会偏向于复杂性而不是实用性,这给用户增加了将寄存器应用于复制/删除操作的负担-通常,人们只是想粘贴复制的内容,而“忘记”删除的内容。

但是,与其使用vim复杂的寄存器,不如让它们更方便:选择一个“默认”寄存器来存储最新的删除操作。例如,将删除内容发送到d寄存器(将ac打开以进行即席使用; d是一个很好的助记符):

nnoremap d "dd           "send latest delete to d register
nnoremap D "dD           "send latest delete to d register 
nnoremap dd "ddd         "send latest delete to d register
nnoremap x "_x           "send char deletes to black hole, not worth saving
nnoremap <leader>p "dp   "paste what was deleted
nnoremap <leader>P "dP   "paste what was deleted

这种方法可以防止删除造成麻烦,但不要放弃注册删除操作-可以粘贴(回退)删除的内容,而不是将其丢失在黑洞中(如公认的答案所示)。在上面的示例中,此调用使用两个前导p映射完成。这种方法的好处是,它使您能够选择要粘贴的内容:(a)刚删除的内容,或(b)刚删除的内容。


0

寄存器0到9是您最近拖动或剪切等的东西,并且不包括已删除的东西等。因此,如果您猛拉/剪切某物,它也在寄存器0中,即使您整天都说删除的东西,也要记录0仍然是您拉动/剪切的最后一件事。

yiw#同时进入默认寄存器和寄存器0

它会拉动光标所在的单词

删除的东西等将进入默认寄存器,但不注册0

在标准模式下:

“ 0p#放入寄存器0的内容

在插入模式下:

ctrl-r 0#输入寄存器0的内容

我还有一个朋友,他总是拉票/切记要注册x哈哈。

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.