连接每 3 行以制表符分隔 (vim)

Join every 3 lines spearated with tab (vim)

我想用制表符作为分隔符连接文件的每 3 行。如何使用 Vim 完成此操作?

我知道宏机制,但我正在寻找更优雅的东西。

我建议使用宏,手动执行一次并将其绑定到一个键中,但如果您想经常使用它,我建议您在 .vimrc[=11 中添加一个映射命令=]

我会使用两个 :help :normal 命令……

  1. 在每一行添加一个制表符:

     :%normal A^i
    

    <C-v><Tab> 获得文字 ^i

  2. 加入每组三行:

     :%normal 3J
    

事实证明这行得通:

:g/\n/,+1s//\t

:global 将匹配缓冲区中的每一行(或者在范围内,如果你传递一个范围。)

/\n/ 被用作将匹配每一行的正则表达式,在本例中,是在换行符本身上。我们可以使用 /^/ 之类的东西(或者 /.//\S/ 来匹配非空行或非空行),这里我们使用 /\n/ 因为我们想要在以下 :s 中使用该模式,因此我们可以在此处省略它以使用相同的模式。

然后,对于 :g 处理的每一行,我们使用该行的范围直到第 +1 行。这意味着两行,在这种情况下,当前行和下一行。由于我们要连接三行,我们要替换两行的换行符,所以从当前行到第 +1 行。 (您可以将其概括为使用 + 您要加入的块中的行数减去二。)

最后,我们执行替换 s//\t,相当于 s/\n/\t/(使用空模式将匹配之前使用的 on,在本例中传递给 :g .) 此 :substitute 将用制表符替换匹配的换行符,有效地连接匹配的行。由于我们使用两行的范围,它一次只会执行两行,有效地替换两个换行符,这将连接三行。

这是有效的,因为当对受影响的行进行编辑时,:global 的方式有效。它首先“标记”应该执行的行,但是如果该行不再存在,它将跳过它。因此,虽然它会首先标记每一行,但当 :s 将每第二行和第三行连接到块中的第一行时,它们上的标记将不再存在,因此最终结果是 :g不会再次尝试处理这一行,而是会继续到下一个“标记”行,然后它将成为下一个块的开始。