在vim中按行号执行yank操作

4
我有一个文件,我想要做以下操作。
- copy every n lines starting from m (m,m+n,m+2n, ...)
- copy line number 2, 5, 27, ... by specifying line numbers.

谢谢

2个回答

7
要复制每 N 行,您可以使用具有选择行的表达式的 :global
:let @a = ''
:g/^/if line('.') % 3 == 0 | yank A | endif

对于显式行,我会按顺序调用 :yank 命令:

2yank a | 5yank A | 27yank A

这个使用将内容复制到大写寄存器来进行追加。


非常感谢!但是,1. 在你的第一段代码中,n和m在哪里?2. 第二段代码中,a和A有什么区别? - eli
我认为在你的例子中n=3。 - eli
是的,我选择了n=3,你只需要添加一个偏移量:(line('.') + 1) % 3;试验一下,你就会明白。 - Ingo Karkat

1
除了Ingo发布的:g解决方案,您还可以使用:s命令。首先,您需要准备模式。例如,要显式匹配每第三行,您可以使用模式\%3l\|\%6l\|\%9l等。因此,首先让我们将生成的模式保存在变量中(为了简化它,我们只考虑前100行):
:let lines=range(3,100,3)

这将创建一个从3开始以3递增的所有行号列表。如果您需要一些不遵循任何算术规则的特殊行号,只需将列表定义为如下形式:
:let lines=[2,5,26,57,99]

然后我们需要将其生成为一个模式,这样我们就可以在:s命令中使用它:
:call map(lines, '''\%''.v:val.''l''')

这将行号转换为形式为\%数字l的模式。因此,我们有一个匹配每个所需行的模式,但首先需要初始化一个结果列表变量:
:let result = []

我们现在可以将此输入到:s命令中:
:exe ":%s/". join(lines, '.*\|'). '/\=add(result, submatch(0))/n'

所有匹配的行现在都包含在列表result中,可以通过以下方式将其复制到剪贴板:
:let @+=join(result, "\n")

或者您可以将其粘贴到一个临时缓冲区中:
:new +exe\ append(0,result)

(请注意,exe和附加调用之间的空格需要进行转义)。
请注意,此解决方案至少需要 Vim Patch 7.3.627
根据情况,我会使用这种方法或Ingo指出的方法。

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