如何在Vim中提取一行文本并将其内联粘贴?

69

假设我有以下代码:

thing();
getStuff();

我想使用yy命令获取getStuff(),然后前进到thing(),将光标放在上,再通过p命令粘贴,但是由于我已经拷贝了整行,因此p会把getStuff()粘贴回到原来的位置。

我知道你可以先将光标移动到getStuff()行的开头,然后通过^D命令删除直到行末的字符,然后p就能实现我想要的效果。然而,我认为输入^D比输入yy更麻烦。

有没有一种方法可以用yy复制,但却可以内联粘贴该行呢?


有人提到了 yy,然后在插入模式下使用 <C-r>*,但如果它能去掉制表符和换行符就太棒了。 - tester
在插入模式中,将光标放在您想要的位置,使用 Ctrl + r,然后 "。现在,按下 Esc k Shift + j。最后一组组合将剥离制表符和换行符。 - Badran
4个回答

53
问题在于yy会复制整行文本,包括换行符。一种替代方法是从行首复制到行尾,然后粘贴。

^y$

  • ^跳转至行首字符。
  • y复制至
  • $行末。

// 致谢:tester和Idan Arye的Vim高尔夫改进。


虽然这很不错,解决了我的新行问题,但是假设在 getStuff() 之前我有一堆制表符..结果我最终会复制 \t\t\t\tgetStuff()..然后我最终还得返回去编辑掉...我希望有一种方法可以用粘贴命令去除制表符和换行符。 - tester
啊,看起来可以用 ^y$ 这个正则表达式,虽然很短,但我仍希望找到一个删除制表符的函数,这样就不必使用 ^ 了。 - tester
13
你可以使用 _y$。下划线 _ 的作用是 [count] - 1 行向下,找到第一个非空字符 |按行|.。没有 [count],作用与 ^ 相同,但 _ 更容易在键盘上操作。 - Idan Arye
^和_会跳到行中第一个非空白字符,因此它们不会捕捉制表符。如果您想要前导空格,请使用0代替,例如0y$。 - Alex Martini
2
我在我的vimrc中有nnoremap Y y$,这样Y会将当前行的末尾复制(类似于CD)。这将为上述解决方案节省一个按键。 - Prince Goulash

43

使用 yiw("yank inner word")代替 yy 来精确复制所需内容:

yy 是整行复制,包括回车符,你可以在无名寄存器 ("") 中通过 :registers 命令查看。该寄存器用作黏贴操作的源。请参考 :help ""

Vim 对于没有指定寄存器的任何复制命令 (pP) 都使用无名寄存器中的内容。此外您还可以通过名称 " 访问它。这意味着您必须输入两个双引号。向 "" 寄存器写入将会写入到寄存器 "0

使用 yiw 的另一个好处是您不必在要复制的 "word" 的开头位置!


1
啊,这很好,因为即使你的光标在单词中间,它也会将整个单词移动到一行。谢谢。 - tester
1
在某些情况下,您可能会发现 y i W 很有用。 - young_souvlaki
我在哪里可以找到关于 yiwyiW 这样的命令的文档?仅仅输入 :h yiw:h inner 或者前往 :h yank 并搜索 "inner" 并不能起到作用。Stack 对我来说成为了事实上的手册,但是当我离线时这并没有帮助。 - Clint Chelak
1
@ClintChelak 请查看:help text-objects。它们有很多,不仅适用于动作y - bheeshmar

11

简化对相同文本模式操作的例程的一种方法是定义映射,这些映射模仿文本对象选择命令。

以下两个映射对分别为可视模式和待操作模式提供了一种选择当前行中除换行符之外的所有内容(al),以及从当前行的第一个非空字符到最后一个非空字符(包括)的所有内容(il)。

:vnoremap <silent> al :<c-u>norm!0v$h<cr>
:vnoremap <silent> il :<c-u>norm!^vg_<cr>
:onoremap <silent> al :norm val<cr>
:onoremap <silent> il :norm vil<cr>

因此,如果要逐个字符(而不是按行)粘贴要复制的行内容,可以使用yalyil命令进行复制,然后像往常一样使用p命令进行粘贴,而不是使用yy


9

一种效率较低但简单的方法:

  • v 选中单词或多个单词,
  • y 复制所选中的单词或多个单词,
  • p (在要粘贴的行末)粘贴复制的内容。

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