ChatGPT解决这个技术问题 Extra ChatGPT

在 Vim 中有没有办法在不将文本放入寄存器的情况下删除?

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

但是,当我删除要替换的代码块时,该块本身会进入寄存器,从而擦除我刚刚拉出的块。所以我养成了拉动,然后插入,然后删除我不想要的东西的习惯,但是对于大块代码,试图将插入的块和要删除的块分开会变得很混乱。

那么在 Vim 中替换文本最灵巧、最快捷的方法是什么?

有没有办法删除文本而不将其放入寄存器?

有没有办法说,例如“替换下一个单词”或“替换到下一段”

还是以某种方式使用多寄存器功能的最佳方法?

vim-easyclip (github.com/svermeulen/vim-easyclip) 旨在解决这个确切的问题
我问了 a question, unknowingly (at the time) duplicate of your actual problem,但没有问太多标题问题。 TL;DR - 替换为您使用 viwp(用于 word)拉出的内容。

i
ib.

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

"_d

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


起初我以为这个命令不能正常工作。然后我意识到我使用的是美式键盘的“死键”版本。使用这种键盘布局,我必须输入 "<space>_d。实际键入“.
关于仅在空行上选择性地执行此操作的任何想法? (如果我 dd 在空行上它会进入黑洞,否则它dd就像正常一样)。
要删除一个字符,请尝试:"_x
这是标准文本编辑器胜出的一个领域。您只需按删除键。
您还可以使用 yy 或 '3yy'(或其他)来拉取某些内容,这会将其放入未命名的寄存器中,但也可以放入 0。然后您可以继续使用 "0p 粘贴它,尽管之后使用了 d .
O
Olivier Verdier

是的。它比首先删除“旧”文本稍微复杂一些,但是:

我从..

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 documentation on numbered register


如果你用 选择行,你只用 d 删除它们,而不是 dd
1 到 9 适用于删除。要粘贴最后一个真正被拉出的东西(使用'y'),您必须使用“0p。这在您首先拉出打算替换其他东西的东西,但随后其他东西会覆盖默认粘贴寄存器的情况下很有用。
如需更多撤消复杂性,请查看 the Gundo (graphical undo) script
@RafaeldeF.Ferreira:您的评论不是对这个问题的回答,但它实际上可能解决了导致 OP 首先提出问题的实际问题。对我来说,这才是真正的问题。
w
wisbucky

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

例如,我们拉出“foo”并删除“bar”——注册表 0 仍然包含“foo”!因此可以使用 "0p 粘贴“foo”


E
Eric Duminil

有一个简单的映射很方便,它可以让你用缓冲区替换当前的选择。

例如当你把它放在你的 .vimrc

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

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

解释:

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

如需更高级的版本,请查看:stackoverflow.com/questions/290465/…
我想使用 vmap <C-P> "_dP
您可以只放置文本而不删除选择。例如 Vp 立即将您当前的行替换为被拉出的行。
此解决方案无法解决经常用于删除的 d 的问题。
M
Magnus

我将以下内容放入我的 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

现在我从剪贴板寄存器中拉出和放入,不必关心默认寄存器会发生什么。另一个好处是我可以轻松地从其他应用程序粘贴。我知道我失去了一些功能(我不再能够为剪贴板寄存器和默认寄存器管理不同的复制信息),但无论如何我都无法跟踪多个寄存器/剪贴板。


除了所有这些重新映射之外,您还可以使用 set clipboard=unnamedset clipboard=unnamedplus,它们分别将默认剪贴板更改为 *+
@Steve如果你这样做,那么 d 也会覆盖到剪贴板寄存器的最后一次猛拉,这是问题试图避免的。
@ 79E09796,我并不是要暗示它会;我在评论这个答案,而不是原来的问题。
我把这些放在我的 .vimrc 中,现在 yanking 不起作用。知道为什么吗?
@tba 用 nnoremap(两个 n)替换 noremap,它应该可以正常工作。
W
Wayne

默认情况下,所有 yank 和 delete 操作都会写入未命名的寄存器。但是,最近的 yank 和最近的删除总是(单独)存储在编号的寄存器中。寄存器 0 保存最新的 yank。寄存器 1-9 保存 9 个最近的删除(其中 1 是最近的)。

换句话说,删除会覆盖未命名寄存器中最近的 yank,但它仍然存在于 0 寄存器中。其他答案中提到的黑洞寄存器技巧 ("_dd) 有效因为它可以防止覆盖未命名的寄存器,但这不是必需的。

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

"0p

这是一个很好的参考:

http://blog.sanctum.geek.nz/advanced-vim-registers/


E
EBGreen

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

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

这很好用,除非您想粘贴多个选择。
C
Community

强调什么 EBGreen said

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

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

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

:registers

在执行 dbr's answer 之类的操作时,该命令可以更轻松地确定您想要的寄存器。您还将看到 /,%,# 寄存器。 (另见:help registers

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


m
maeghith

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

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

例子:

在一个文本文件中:

1| qwer
2| asdf
3| zxcv
4| poiu

使用以下顺序:ggVjyGVkp 您将以:

1| qwer
2| asdf
3| qewr
4| asdf

解释:

gg:转到第一行

V:以整行启动视觉模式

j:向下一行(选择从前一行开始,这会使选择向下一行)

y:拉到默认缓冲区(两条选定的行,它会自动退出可视模式)

G:转到最后一行

V:启动视觉模式(和之前一样)

k:上一行(和以前一样,启用可视模式,这会将选择增加一行)

p:粘贴(在最后两行上进行选择,它将用缓冲区中的任何内容替换这些行 - 在这种情况下是前两行)

这有点不方便将最后一个块放在缓冲区上,因此在某种程度上不希望重复粘贴相同的东西,因此您需要将源保存到具有类似 "ay 的命名缓冲区(到缓冲区称为“a”)并使用 "ap 之类的内容粘贴(但如果您正在编程,您可能不想粘贴多次,而是创建一个函数并调用它,对吧?正确?)。

如果您只使用 vi,那么您将不得不使用隐形标记而不是可视模式,:he mark 了解更多信息,对不起,我对这个隐形标记不太好,我很受污染视觉模式。


S
Swaroop C H

对于“替换单词”,请在正常模式下尝试 cw

对于“替换段落”,请在正常模式下尝试 cap


对于“替换 下一段”,请在正常模式下尝试 c}
为什么“帽”会这样做? “a”和“p”不是代表“追加”和“粘贴”吗?
@WiSaGaN“ap”代表“一段”:vimhelp.appspot.com/motion.txt.html#object-select
T
Torben

针对懒人的微创解决方案:

寄存器 0 总是包含最后一个 yank(正如 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: 剪切命令现在是 "0d 而不仅仅是 d。但是由于我很懒,这对我来说太长了;)因此我使用了以下映射:

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

前导键默认为 \,因此您可以通过键入 \d\D 轻松剪切文本。

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

set timeout timeoutlen=3000 ttimeoutlen=100

E
EBGreen

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

:h d

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


["x]d{motion} Delete text that {motion} moves over [into register x] -- Vim :h d
V
Victoria Stuart

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

我尝试了接受的答案 ("_d) 中的建议,但没有奏效。

但是,从 https://vi.stackexchange.com/questions/122/performing-certain-operations-without-clearing-register 接受的答案/评论中,我将其添加到了我的 ~/.vimrc,它有效(您可能必须重新启动 Vim):

nnoremap x "_x

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


g
gregory

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

这种方法可以防止删除破坏 yanks 但不会放弃注册删除 - 可以粘贴(返回)已删除的内容,而不是将其丢失在黑洞中(如已接受的答案中所示)。在上面的示例中,这种召回是通过两个领导者 p 映射完成的。这种方法的一个好处是,它使您能够选择要粘贴的内容:(a) 刚刚拉出的内容,或 (b) 刚刚删除的内容。


很好的解决方案。对我来说更直观的粘贴映射是 nnoremap dp "dpnnoremap dP "dP
这很棒。爱它。
佚名

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


但在默认模式下删除任何大量文本都是缓慢的
e
expelledboy

我在正确的上下文中使用的两种解决方案是:

使用 Vims VISUAL 模式突出显示要替换的内容,然后粘贴寄存器。

我使用这个主要是出于习惯,因为我很久以后才找到第二个解决方案,例如

yiw   " yank the whole word
viwp  " replace any word with the default register

扬克环。使用此插件,您可以使用键绑定 +

将先前编号的寄存器替换为刚刚粘贴的寄存器。

基本上你可以随意粘贴,但是当你意识到你已经覆盖了默认寄存器从而丢失了你真正想要粘贴的内容时,你可以<C-P>从 YankRing 历史记录中查找和替换!

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


H
Hieu Nguyen

我为您的目的找到了一个非常有用的映射:

xnoremap p "_dP

删除的文本被放入“黑洞寄存器”,而被抽出的文本仍然存在。

来源:http://vim.wikia.com/wiki/Replace_a_word_with_yanked_text


J
JayG

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

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


C
Clueless

我经常犯错误,当我按照命令 'y'ank 然后 '"_d'elete into a black hole 然后 'p'aste 0 寄存器,这是最后复制的文本被推送到的地方。


V
Vic Goldfeld

对于 Dvorak 用户,一种非常方便的方法是将不需要的文本删除到“1 寄存器而不是”_黑洞寄存器,如果只是因为您可以使用相同的 shift 按和快速的小指动作按“+1”,因为 1 是Dvorak 中 " 正上方的键(另一方面,加号 d 使整个命令快得不得了)。

当然,“1 寄存器可以用于其他用途,因为它很方便,但除非你有比替换文本更常见的目的,否则我会说这是一个很好的寄存器用途。


A
Adrien Vakili

对于 emacs-evil 用户,可以在粘贴后触发函数 (evil-paste-pop),并循环遍历 kill-ring 中的先前条目。假设您将它绑定到 <C-p>(Spacemacs 中的默认值),您将点击 p,然后根据需要点击任意数量的 <C-p>


E
Ed Kolosovsky

对于那些将 JetBrans IDE(PhpStorm、WebStorm、IntelliJ IDEA)与 IdeaVim 一起使用的人。您可能在重新映射 nnoremap d "_d 并使用它删除行 dd 时遇到问题。您可能的解决方案:nnoremap dd "_dd

youtrack 上有问题,请为他们投票:https://youtrack.jetbrains.com/issue/VIM-1189 https://youtrack.jetbrains.com/issue/VIM-1363


非常感谢您花时间发布此回复。我在世界各地寻找过用 IdeaVim 解决这个问题的方法。
s
snap

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

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

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

来自这里的答案(和评论):How to paste over without overwriting register

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

PS:如果您需要一个更简单的变体,它也适用于 intellj idea 插件 vim-simulation,您可以使用这个(缺点:即使给出了另一个寄存器用于粘贴,也会覆盖未命名的寄存器):

vnoremap p pgvy


C
Community

寄存器 0 到 9 是您拉动或剪切等的最新内容,并且不包括已删除的内容等。因此,如果您拉动/剪切某些内容,它也在寄存器 0 中,即使您在那之后一整天都说删除的东西,请注册 0仍然是你拉/切的最后一个东西。

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

它拉动光标所在的单词

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

在标准模式下:

"0p #放寄存器0的内容

在插入模式下:

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

我还有一个朋友总是拉/切注册 x 大声笑。


我已经知道 viw,但从未意识到:ciw diw yiw
m
mohammadreza berneti

下面的 vscode 设置应该允许例如 dd 和 dw 变成 "_dd 和 "_dw,它们现在可以在我们的重映射器中正常工作。

{
     "vim.normalModeKeyBindingsNonRecursive": [
        {
            "before": ["d"],
            "after": [ "\"", "_", "d" ]
        }
    ]
}

s
sebtheiler

您可以使用以下命令创建一个简单的宏:q"_dwq

现在要删除下一个单词而不覆盖寄存器,您可以使用 @d


Z
ZhiyuanLck

主要问题是在可视模式下使用 p。在您以可视模式粘贴内容后,以下功能将恢复未命名寄存器的内容。

 function! MyPaste(ex)
  let save_reg = @"
  let reg = v:register
  let l:count = v:count1
  let save_map = maparg('_', 'v', 0, 1)
  exec 'vnoremap _ '.a:ex
  exec 'normal gv"'.reg.l:count.'_'
  call mapset('v', 0, save_map)
  let @" = save_reg
endfunction

vmap p :<c-u>call MyPaste('p')<cr>
vmap P :<c-u>call MyPaste('P')<cr>

用法和以前一样,寄存器"的内容没有改变。


J
Jacob Vanus

我发现一开始就拉入“p”缓冲区更容易。

复制(又名:猛拉)

# highlight text you want to copy, then:
"py

粘贴

# delete or highlight the text you want to replace, then:
"pp

优点(与删除到特定寄存器相反):

“pp很容易上手

不会在删除时意外覆盖您的粘贴缓冲区。


Z
Zaid Gharaybeh

noremap mm m

noremap mx "_x

这就是我的处理方式。