在Vim中是否有一种方法可以删除而不将文本放在寄存器中?

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

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

那么,在Vim中替换文本的最灵活、最快的方法是什么呢?

  • 是否有一种方法可以删除文本而不将其放入寄存器?
  • 有一种说法吗?“替换下一个单词”或“替换到下一段”
  • 还是使用多寄存器特性的最佳方式?
85859 次浏览

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

:h d

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

对于你给出的具体例子,如果我理解了问题,那么这可能是可行的:

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

如果你用的是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更多关于这个,我很抱歉,但我不太擅长这种不可见标记的东西,我很受可视模式的污染。

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

"_d

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

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

对于'replace word',请在正常模式下尝试cw

对于'replace段落',在正常模式下尝试cap

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

我从。开始。

line1
line2
line3
line4


old1
old2
old3
old4

转变+v选择第1行,第2行,第3行和第4行,并用d命令删除它们

然后用同样的方法删除原来的1-4行。

然后,做

"2p

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

最后得到

line1
line2
line3
line4

< >强引用: 编号寄存器上的Vim文档 < / p >

在windows版本中(可能在Linux中也是如此),你可以使用"*y(即在你的yank命令前加双引号和星号)将数据拉入系统的复制/粘贴缓冲区。

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

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

.

.

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

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

例如,当你把这个放在你的。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

我把以下内容放在我的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

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

我经常犯一个错误,当我执行命令“y'ank then '”_d'elete into a black hole then 'p'aste。我更喜欢'y'ank,然后删除我喜欢的,然后从0寄存器中删除' ' 0p',这是最后复制的文本被推入的地方。

为了强调EBGreen说:

如果在选择文本时进行粘贴,则所选文本是带有粘贴文本的取代

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


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

:registers

当执行类似dbr的回答这样的操作时,该命令可以更容易地找出你想要的寄存器。您还将看到/,%,#寄存器。(另见:help registers)


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

我在适当的情况下使用的两种解决方案是;

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

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

yiw   " yank the whole word
viwp  " replace any word with the default register
  • YankRing。有了这个插件,你可以使用键绑定<ctrl>+<p>来替换之前的编号寄存器。

基本上你可以像你想要的那样进行粘贴,但是当你意识到你已经覆盖了默认寄存器,从而丢失了你真正想要粘贴的东西时,你可以<C-P>从YankRing历史中找到并替换!

其中一个肯定有插件…

对于Dvorak用户来说,一个非常方便的方法是将不需要的文本删除到“1寄存器”而不是“_黑洞寄存器”中,如果只是因为你可以在Dvorak中按“+ 1与相同的shift键和快速的小指运动,因为1是紧靠上面的键”(另一方面是PLUS d,这使得整个命令速度非常快)。

当然,1寄存器也可以用于其他事情,因为它很方便,但除非你有一个比替换文本更常见的目的,否则我认为它是一个很好的使用寄存器的方法。

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

xnoremap p "_dP

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

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

懒人的微创解决方案:

寄存器0总是包含最后一个yank(正如拉斐尔alex2k8idbrii已经提到的那样)。不幸的是,一直选择寄存器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

cut命令现在是"0d而不是d。但因为我很懒,这对我来说太长了;)因此,我使用以下映射:

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

默认情况下,先导键是\,所以你可以通过输入\d\D轻松地剪切文本。

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

set timeout timeoutlen=3000 ttimeoutlen=100

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

换句话说,在其他答案中提到的黑洞寄存器技巧("_dd)是有效的,因为它可以防止覆盖未命名的寄存器,但这不是必要的。

你可以使用双引号引用一个寄存器,所以可以像这样粘贴最近拉出的文本:

"0p

这是一个很好的参考:

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

你可以使用下面的解决方案,这是简单的,最适合我:

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

这是来自这里的回答(和评论): 如何粘贴而不覆盖寄存器

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

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

vnoremap p pgvy

对于emacs-evil用户,函数(evil-paste-pop)可以在粘贴后被触发,并在kill-ring中循环之前的条目。假设你将它绑定到<C-p> (Spacemacs中的默认值),你将点击p,然后根据需要添加许多<C-p>

我的情况:在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删除的字符不再填充最新的寄存器。

对于那些使用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 < / p >

Vim有时更倾向于复杂性,而不是实用性,这给用户带来了应用寄存器来复制/删除操作的负担——通常情况下,用户只想粘贴复制的内容,而“忘记”删除的内容。

但是,与其与vim复杂的寄存器作斗争,不如让它们更方便:选择一个“默认”寄存器来存储最新的删除。例如,发送删除到d寄存器(让a-c打开以供特别使用;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)刚刚删除的内容。

寄存器0到9是最新的东西你拉或削减等,不包括删除的东西等。所以如果你拉/切一些东西,它也在寄存器0中,即使你说在那之后删除了东西,寄存器0仍然是你拉/切的最后一个东西。

yiw#转到默认寄存器和寄存器0

它猛拉光标所在的单词

删除的东西等将去默认寄存器,但不是寄存器0

标准模式:

输入寄存器0的内容

插入模式:

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

我也有一个朋友,他总是猛拉/切来注册x,哈哈。

下面的vscode设置应该允许dd和dw变成"_dd和"_dw,现在在我们的remapper中可以正常工作。

{
"vim.normalModeKeyBindingsNonRecursive": [
{
"before": ["d"],
"after": [ "\"", "_", "d" ]
}
]
}
你可以创建一个简单的宏: q"_dwq < / p >

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

主要问题是在可视模式下使用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>

使用方法与以前相同,登记册的内容与quot;没有改变。

我发现从一开始就更容易插入'p'缓冲区。

复制(又名:yank)

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

粘贴

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

优点(相对于删除到特定寄存器):

  • "pp很容易上手
  • 不会在删除时意外覆盖粘贴缓冲区。

noremap mm m

而且

noremap mx "_x

是我的处理方式。