在 Vim 中,有没有一种方法可以在不将文本放入寄存器的情况下进行删除?
-
09-06-2019 - |
题
使用 Vim,我经常想用我刚刚拉出的代码块替换代码块。
但是,当我删除要替换的代码块时,该块本身会进入寄存器,从而擦除我刚刚拉出的块。所以我养成了先拉动,然后插入,然后删除我不想要的东西的习惯,但是对于大块代码,试图将插入的块和要删除的块分开会变得很混乱。
那么在 Vim 中替换文本最灵活、最快的方法是什么?
- 有没有办法删除文本而不将其放入寄存器?
- 有没有办法说例如“替换下一个单词”或“替换到下一段”
- 或者是以某种方式使用多寄存器功能的最佳方法?
解决方案
要删除某些内容而不将其保存在寄存器中,可以使用“黑洞寄存器”:
"_d
当然,您也可以使用任何其他不包含您感兴趣的内容的寄存器。
其他提示
是的。它比先删除“旧”文本稍微复杂一些,但是:
我从..开始
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 文档
VIM 文档: 编号寄存器0包含最新Yank命令中的文本,除非命令指定了另一个带有[X]的寄存器。
例如。我们猛拉“foo”并删除“bar”——注册表 0 仍然包含“foo”!因此“foo”可以使用粘贴 "0p
拥有一个简单的映射非常方便,它可以让您用缓冲区替换当前选择。
例如,当您将其放入 .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
我将以下内容放入我的 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
现在,我可以从剪贴板寄存器中拉入或放入,而不必关心默认寄存器会发生什么。另一个好处是我可以轻松地从其他应用程序粘贴。我知道我正在失去一些功能,但无论如何我都无法跟踪多个寄存器/剪贴板。
对于您给出的具体示例,如果我理解这个问题,那么这可能会起作用:
*Highlight what you want to put somewhere else
*delete (d)
*Highlight the code that you want it to replace
*paste (p)
默认情况下,所有复制和删除操作都会写入未命名的寄存器。但是,最近的猛拉和最近的删除始终(单独)存储在编号寄存器中。登记册 0
持有最近的猛拉。寄存器 1-9
保存 9 个最近删除的内容( 1
是最新的)。
换句话说, 删除会覆盖未命名寄存器中最近的复制,但它仍然存在于 0
登记。 黑洞注册技巧("_dd
其他答案中提到的)之所以有效,是因为它可以防止覆盖未命名的寄存器,但这不是必需的。
您使用双引号引用寄存器,因此可以像这样粘贴最近复制的文本:
"0p
这是一个很好的参考:
如果您使用 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
有关于此的更多信息,我很抱歉,但我不太擅长这种隐形标记的事情,我对视觉模式非常污染。
对于“替换单词”,请尝试 cw
在正常模式下。
对于“替换段落”,请尝试 cap
在正常模式下。
针对懒人的微创解决方案:
登记 0
始终包含最后一次猛拉(如 拉斐尔, 亚历克斯2k8 和 伊德布里伊 已经提到过)。不幸的是选择了注册 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
.
这样,除了隐式的行为之外,标准行为被保留 p
和 P
笔划,现在使用寄存器 0
默认情况下。
提示1: 现在的剪切命令是 "0d
而不是仅仅 d
. 。但由于我很懒,这对我来说太长了;)因此我使用以下映射:
noremap <LEADER>d "0d
noremap <LEADER>D "0D
领导者关键是 \
默认情况下,因此您可以通过键入轻松剪切文本 \d
或者 \D
.
提示2: 多键映射的默认超时非常短。您可能希望增加它以便在选择寄存器时有更多时间。看 :help timeoutlen
有关详细信息,我正在使用:
set timeout timeoutlen=3000 ttimeoutlen=100
好吧,首先执行这个命令:
:h d
然后你会意识到你可以删除到特定的寄存器中。这样您就不会更改默认寄存器中的内容。
在插入模式下删除的文本不会进入默认寄存器。
我在正确的情况下使用的两种解决方案是:
- 使用 Vims 突出显示要替换的内容
VISUAL
模式然后粘贴寄存器。
我使用这个主要是出于习惯,因为我很晚才找到第二个解决方案,例如
yiw " yank the whole word
viwp " replace any word with the default register
- 扬克环. 。通过此插件,您可以使用键绑定
<ctrl>+<p>
将之前编号的寄存器替换为您刚刚粘贴的寄存器。
基本上,您可以按照自己的意愿进行粘贴,但是当您意识到您已经覆盖了默认寄存器,从而丢失了您真正想要粘贴的内容时,您可以 <C-P>
从 YankRing 历史记录中查找和替换!
其中之一必须有插件......
我找到了一个非常有用的映射来满足您的目的:
xnoremap p "_dP
删除的文本被放入“黑洞寄存器”中,而被拉出的文本仍然存在。
来源: http://vim.wikia.com/wiki/Replace_a_word_with_yanked_text
在 Windows 版本中(也可能在 Linux 中),您可以使用以下命令拉入系统的复制/粘贴缓冲区 "*y
(IE。在你的 yank 命令前面加上双引号和星号)。
然后,您可以正常删除可替换行并使用以下命令粘贴复制的文本 "*p
.
当我按照“y”ank然后“”_d”elete到黑洞然后“p”aste的命令时,我经常犯一个错误。我更喜欢“y”ank,然后按我喜欢的方式删除,然后从 0 寄存器中“”0p”,这是最后复制的文本被推送到的位置。
我的情况:在 Normal
模式,当我使用删除字符时 x
按键,这些删除会覆盖我最新的寄存器——使我想使用删除字符的编辑变得复杂 x
并粘贴我最近的寄存器中的内容(例如在两个或多个位置粘贴相同的文本)。
我尝试了已接受答案中的建议("_d
),但没有成功。
但是,从接受的答案/评论来看 https://vi.stackexchange.com/questions/122/performing-certain-operations-without-clearing-register, ,我将其添加到我的 ~/.vimrc
, ,它有效(你可能需要重新启动 Vim):
nnoremap x "_x
也就是说,我现在可以进行正常的猛拉(y
), 删除 (d
),并粘贴(p
) 命令——以及我使用删除的字符 x
不再填充最新的寄存器。
对于 Dvorak 用户来说,一种非常方便的方法是将不需要的文本删除到“1”寄存器而不是“_黑洞”寄存器中,因为您可以使用相同的 Shift 键和快速小指动作来按“+1”,因为 1 是Dvorak 中“”上方的键(另一方面,PLUS d 使整个命令快得要命)。
当然,“1 寄存器可以用于其他用途,因为它很方便,但除非您有比替换文本更常见的目的,否则我会说这是寄存器的一个很好的用途。
对于那些主要对在通过虚拟选择和粘贴替换文本时不覆盖未命名寄存器感兴趣的人来说。
您可以使用以下解决方案,该解决方案很简单并且最适合我:
xnoremap <expr> p 'pgv"'.v:register.'y'
这是来自这里的答案(和评论):如何粘贴而不覆盖寄存器
它首先经过选择,然后再次选择包含新文本的选择(gv)。现在是最后在可视模式下使用的寄存器(通常是未命名的寄存器,但如果您使用另一个寄存器进行粘贴,也可以无副作用)。然后再次将新值拉入寄存器。
附:如果您需要一个更简单的变体,也可以与 intellj idea 插件 vim-simulation 一起使用,您可以采用这个(缺点:即使提供了另一个寄存器用于粘贴,也会覆盖未命名的寄存器):
vnoremap p pgvy
对于 emacs-evil 用户,该功能 (evil-paste-pop)
可以在粘贴后触发,并循环浏览终止环中的先前条目。假设你将它绑定到 <C-p>
(Spacemacs 中的默认设置),你会点击 p
随后有尽可能多的 <C-p>
如所须。