每三行用制表符合并(vim)

3

我想用制表符作为分隔符加入文件中每3行的内容,如何在 Vim 中实现?

虽然我知道宏机制,但我正在寻找更优雅的解决方法。


1
你可以尝试使用 :%norm A<c-v tab><c-v esc>3J - Lieven Keersmaekers
:( J 命令会删除制表符。解决方法是将我的答案中的 <c-v tab 替换为一个唯一的字符/字符串,然后进行查找/替换。 - Lieven Keersmaekers
3个回答

4

我会选择两个:help :normal命令...

  1. Append a tab to every line:

     :%normal A^i
    

    with the literal ^i being obtained with <C-v><Tab>.

  2. Join every group of three lines:

     :%normal 3J
    

也许是我的配置问题,我还没有检查过,但 %normal 3J 会将制表符替换为空格。 - Lieven Keersmaekers
@LievenKeersmaekers J可以去除缩进,但我的制表符在行末,因此不会受到影响。 - romainl
不是我尝试过了。一定是我的配置问题。 - Lieven Keersmaekers
肯定是我的配置问题。gvim -u NONE 可以工作。很可能是 expandtab 的问题。 - Lieven Keersmaekers
1
@LievenKeersmaekers 顺便说一下,我在这里和其他地方测试发布的内容的首选是$ vim -Nu NONE - romainl
显示剩余2条评论

4

原来这个可行:

:g/\n/,+1s//\t
:global 将匹配缓冲区中的每一行(或者在你传递一个范围时,范围内的每一行)。

/\n/ 是一个正则表达式,将匹配每一行,这里匹配的是换行符本身。我们可以使用像 /^/ (或者也许是 /.//\S/ 来匹配非空或非空白行),但在这里我们使用 /\n/,因为我们希望在下面的 :s 中使用该模式,所以我们可以省略它并使用相同的模式。

然后,对于 :g 处理的每一行,我们使用该行到行 +1 的范围。这意味着两行,在这种情况下,当前行和下一行。由于我们想要连接三行,因此我们要替换两行上的行分隔符,从当前行到行 +1。(您可以将其推广到使用需要连接的块中行数减去二再加上号码字符)。
最后,我们执行替换 s//\t,它等价于 s/\n/\t/(使用空模式将匹配先前使用的模式,在这种情况下是传递给 :g 的模式)。这个 :substitute 将匹配的换行符替换为制表符,有效地连接匹配行。由于我们使用两行的范围,它将每次只能连接两行,有效地代替了两个换行符,这将连接三行。
这是因为当影响到的行发生编辑时,:global 的工作方式。它首先“标记”应该被处理的行,但如果该行不再存在,则跳过它。因此,虽然它将首先标记每一行,但当 :s 将第二行和第三行与块中的第一行连接起来时,对它们的标记就不再存在了,因此最终结果是 :global 不会再次尝试处理该行,并继续移动到下一个“标记”的行,这将成为下一个块的开始。

0
我建议使用宏,手动执行一次过程并将其绑定到一个键上,但如果您想经常使用它,我建议您在您的.vimrc中添加一个映射命令。

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