使用Vim,我经常想用我刚刚拉过的代码块替换代码块。
但是,当我删除要替换的代码块时,该代码块本身进入寄存器,该寄存器将擦除我刚刚提取的代码块。因此,我习惯于拉动,然后插入,然后删除我不想要的内容,但是对于大型代码块,尝试将插入的块和要删除的块分开是很麻烦的。
那么,在Vim中替换文字的最流畅最快的方法是什么?
- 有没有办法删除文本而不将其放入寄存器?
- 有没有办法说例如“替换下一个单词”或“替换到下一个段落”
- 还是以某种方式使用多重注册功能的最佳方法?
使用Vim,我经常想用我刚刚拉过的代码块替换代码块。
但是,当我删除要替换的代码块时,该代码块本身进入寄存器,该寄存器将擦除我刚刚提取的代码块。因此,我习惯于拉动,然后插入,然后删除我不想要的内容,但是对于大型代码块,尝试将插入的块和要删除的块分开是很麻烦的。
那么,在Vim中替换文字的最流畅最快的方法是什么?
Answers:
要删除某些内容而不将其保存在寄存器中,可以使用“黑洞寄存器”:
"_d
当然,您也可以使用其他任何不包含您感兴趣的寄存器的寄存器。
"<space>_d
。要实际键入“,需要用空格。
dd
在空行上,它将进入黑洞,否则dd
就像正常情况一样)。
"_x
yy
或'3yy'(或其他任何东西)提取内容,将其放入未命名的寄存器中,也可以放入0中。然后"0p
,尽管d
之后使用过,也可以继续粘贴它。
是的 与先删除“旧”文本相比,它有些复杂,但是:
我从开始
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文档
方便地进行映射很方便,该映射使您可以用缓冲区替换当前选择。
例如,当您将其放入.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
vmap <C-P> "_dP
Vp
将当前行替换为被选中的行。
d
因为该问题通常用于删除。
我在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=unnamed
或set clipboard=unnamedplus
,将默认剪贴板分别更改为*
或+
。
默认情况下,所有拉动和删除操作都会写入未命名的寄存器。但是,最新一次发送和最新删除总是(单独)存储在编号寄存器中。该寄存器0
包含最新的yank。寄存器中1-9
保存了9个最近的删除(1
是最新的)。
换句话说,删除操作会覆盖未命名寄存器中的最新操作,但仍保留在0
寄存器中。"_dd
其他答案中提到的黑洞寄存器技巧()可以起作用,因为它可以防止覆盖未命名的寄存器,但这不是必需的。
您可以使用双引号引用寄存器,因此可以像这样粘贴最近粘贴的文本:
"0p
这是一个很好的参考:
为了强调EBGreen所说的话:
如果在选择文本时粘贴,则所选文本将替换为粘贴的文本。
如果要复制一些文本,然后将其粘贴到多个位置,请使用"0p
粘贴。编号为0的寄存器包含来自最新yank命令的文本。
另外,您可以列出所有寄存器的内容:
:registers
执行dbr的answer等操作时,使用该命令可以更轻松地确定所需的寄存器。您还将看到/,%,#寄存器。(另请参见:help registers
)
最后,签出cW
并cW
更改包含和不包含尾随空格的单词。(使用大写W
字母包括标点符号。)
如果您使用的是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
对此,我很抱歉,但是我对这种不可见标记的东西不太满意,我对可见模式很感兴趣。
对于“替换单词”,请cw
在普通模式下尝试。
对于“替换段落”,请cap
在普通模式下尝试。
c}
在正常模式下尝试。
懒惰的最小侵入性解决方案:
寄存器0
始终包含最后一个键(如Rafael,alex2k8和idbrii所述)。不幸的是,一直选择寄存器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: cut命令现在"0d
不再是d
。但是由于我很懒,这对我来说太长了;)因此,我正在使用以下映射:
noremap <LEADER>d "0d
noremap <LEADER>D "0D
引导键是\
默认设置,因此您可以通过键入\d
或轻松剪切文本\D
。
提示2:多键映射的默认超时时间很短。您可能希望增加它,以便在选择寄存器时有更多时间。有关:help timeoutlen
详细信息,请参阅,我正在使用:
set timeout timeoutlen=3000 ttimeoutlen=100
好吧,首先执行以下命令:
:h d
然后您将意识到可以删除特定的寄存器。这样,您将不会更改默认寄存器中的内容。
["x]d{motion} Delete text that {motion} moves over [into register x]
-Vim:h d
我的情况:在Normal
模式下,当我使用x
按键删除字符时,这些删除会覆盖我最新的寄存器-使要删除字符的编辑变得复杂,x
并粘贴我最近寄存器中的内容(例如,将相同的文本粘贴到两个或两个字符上)更多的地方)。
我在接受的答案("_d
)中尝试了该建议,但是没有用。
但是,从/vi/122/performing-certain-operations-without-clearing-register处的可接受答案/评论中,我将此添加到了我的~/.vimrc
,它可以正常工作(您可能必须重新启动Vim ):
nnoremap x "_x
也就是说,我现在可以执行常规的yank(y
),delete(d
)和paste(p
)命令-并且使用x
不再删除的字符不再填充最新的寄存器。
我在正确的环境中使用的两个解决方案是:
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
对于emacs-evil用户,(evil-paste-pop)
可以在粘贴后触发该功能,并在kill-ring中的先前条目之间循环。假设你把它绑定到<C-p>
(在Spacemacs默认),你会打p
,然后尽可能多的<C-p>
需要。
对于那些最主要的兴趣是通过虚拟选择和粘贴替换文本时不覆盖未命名寄存器的人。
您可以使用以下简单且最适合我的解决方案:
xnoremap <expr> p 'pgv"'.v:register.'y'
它来自此处的答案(和评论): 如何粘贴而不覆盖注册
它首先经过选择,然后再次选择带有新文本的选择(gv)。现在,最后一次在可视模式下使用的寄存器(通常是未命名的寄存器,但是如果您使用另一个寄存器进行粘贴也可以避免副作用)。然后将新值再次拉到寄存器中。
PS:如果您需要一个更简单的变量,该变量也可以与intellj idea插件vim模拟一起使用,则可以使用此变量(缺点:即使给了另一个寄存器用于粘贴,也可以覆盖未命名的寄存器):
vnoremap p pgvy
对于将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
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)刚删除的内容。