如何在Vim中删除(而不是剪切)?

257

如何在不将其放入默认缓冲区的情况下删除一行?

示例:

line that will be copied.

line that I want to be substitued with the previous one.

我想要做什么:

yy
dd
p

但是,Vim会用被删除(剪切)的内容替换最近复制的字符串。我知道我可以使用缓冲区,比如"1yy, dd, 然后"1p,但我总是忘记将复制的字符串放入一个缓冲区,然后需要先粘贴我的内容 (将要复制的行),然后再删除我想要的内容(我想要用之前的内容替换的那一行)。

如何在Vi(m)中真正删除文本而不将其复制?

另一个相关的问题是,我如何在插入模式下向前删除一个单词?我希望有类似于Ctrl+w的功能。


9个回答

276

黑洞寄存器"_可以解决问题,但有更好的解决方案:

当您使用p命令输入该行时,您正在粘贴(易失性的)默认寄存器""的内容,该寄存器已被dd覆盖。但是,您仍然可以从(非易失性的)复制寄存器"0中粘贴,它不会被删除命令dd覆盖。

因此,这些是您想要根据示例使用的命令:

yy
dd
"0p

10
好的,这个答案应该被采纳。手动指定寄存器来粘贴要比每次删除时都指定寄存器容易得多。 - JShorthouse
10
“0p” 不太容易打出来,但我想我可以逐渐习惯这个! - Jon z
3
我会这样用视觉方式记住它。https://imgur.com/sQ2k0NI - Prasanna

203
使用“黑洞寄存器”"_来彻底删除内容:"_d。 使用"_dP黏贴并保留内容以备后续粘贴。
对于第二个问题,您可以使用<C-o>dw<C-o>用于在不离开插入模式的情况下执行普通命令。
当然,您可以设置自己的映射以节省输入。 我有如下设置:
nnoremap <leader>d "_d
xnoremap <leader>d "_d
xnoremap <leader>p "_dP

谢谢,你回答了我的两个问题。但我不明白这些noremap命令如何帮助我。我是不是失去了剪切功能? - MaikoID
5
不,d 仍然是“剪切”,p 仍然是“粘贴”,而 <leader>d 真正删除选定的文本, <leader>p 丢弃选定的文本并粘贴默认寄存器中的内容。 <leader>p 允许我多次粘贴相同的文本,而不必使用命名寄存器。 - romainl
难道你的意思不是 nnoremap <leader>d "_ddxnoremap <leader>d "_dd 吗?现在这样,它会等待下一个序列。 - Amir Shabani
1
@AmirA.Shabani 这是有意的。这些<leader>d映射的目的不是替代dd,而是替代等待动作的d - romainl
天啊,我简直不敢相信我以前从来没有听说过 <C-o>。太棒了! - twhitney
您可以只需添加 noremap <Leader> "_。这样,通过在删除、复制或更改之前按下您的 Leader 键,即可保持剪贴板不变。 - Victor

71

那是我不喜欢vim的事情之一...我最终将dd映射到了我的.vimrc中的黑洞寄存器,自那以后生活一直很美好:

nnoremap d "_d
vnoremap d "_d

11
那么你如何剪呢? - VitalyB
31
使用 x 进行剪切同样也可以称作是“剪切”(cut)。而在任何操作系统中,使用 x 进行剪切也与使用 Ctrl + x 是一致的。 - WesternGun

42

以下映射将产生:

  • d => "删除"
  • leader d => "剪切"
nnoremap x "_x
nnoremap d "_d
nnoremap D "_D
vnoremap d "_d

nnoremap <leader>d ""d
nnoremap <leader>D ""D
vnoremap <leader>d ""d

另外,将"leader"键设置为逗号也是一个不错的习惯,例如:

let mapleader = ","
let g:mapleader = ","

这两个片段将使",d"成为您的新剪切命令。

如果您想要将这些映射与共享系统剪贴板配置一起使用,请参阅https://github.com/pazams/d-is-for-delete获取更多详细信息。


2
我希望我可以给这个答案点赞超过一次——我一直在使用kprobst的答案,但为了切换行,不得不使用yydd,这对我的手指有点吃不消 ;-) - Tahir Hassan
3
这之后,IntelliJ IDEA的表现非常奇怪。dd 没有任何作用。,d也没有任何作用。 - s1n7ax
2
我非常喜欢这个解决方案。有一件事对我不起作用 - 使用,dd删除行。 添加 nnoremap <leader>dd ""dd 后,它开始工作了。 - Alexey
我在Intellij中使用ideavim插件也遇到了一些问题。第二部分好像无法正常工作 :( - Victor
将领导键设置为","会覆盖其"查找上一个"功能,这是移动的核心功能。我不建议这样做。将领导键映射到空格(" ")会提供更好的用户体验。 - Ryan Fisher

10
您可以使用"_d来防止覆盖您复制的文本。您可以将已复制或删除的文本存储在任何寄存器中,使用"_是“黑洞”寄存器,您可以将不关心的东西发送到其中。
要获取更多信息,您可以键入:help "_:help deleting

1

我在我的 .vimrc 文件中使用 noremap ' "_

这样可以保持 dd 的行为,让我可以像以前一样使用它进行剪切。

但是当我真正想要删除某些内容时,只需要使用前缀 '。例如:'dd'dw


0

我最终得到了

nnoremap p "0p
nnoremap P "0P
vnoremap p "0p
vnoremap P "0P
vnoremap x "0x
nnoremap x "0x

始终从0寄存器中粘贴,而不是未命名的寄存器。在可视模式下使用x删除到0寄存器。


0
yy
Vx
p

当处于可视模式时,x 将删除所选内容,因此如果您想删除整行,请先按 V 在可视模式下选择该行,然后按 x 删除所选内容。

5
这将删除的那一行复制到剪贴板中,这正是原帖想要避免的。 - BeefSupreme
不知怎么的,这在Emacs的Evil插件上完美运行。 - Pedro Penna

0

还有另一种解决方案。就是将要复制的行复制到要删除的行上,像这样。

将光标放在要复制的行的开头,然后输入ddVp

  • dd 删除要复制的行
  • V 选择要替换的整行
  • p 将删除的行粘贴到视觉选择上

现在被删除的行在"1寄存器中,而复制的行在"2寄存器中。没有丢失任何内容。

我使用vim 9,不知道哪个旧版本的vim可以使用此方法。如果无法使用,请将以下代码添加到您的.vimrc文件中:

" Make p in Visual mode replace the selected text with the "" register. vnoremap p <Esc>:let current_reg = @"<CR>gvdi<C-R>=current_reg<CR><Esc>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接