我想合并Vim中的两个行块,即取行k到l并将它们附加到行m到n。如果您喜欢伪代码解释:[line[k+ I] + line[m+ I] for I in range(min(l-k, n-m)+1)]。

例如,

abc
def
...

123
45
...

应该成为

abc123
def45

有没有一种很好的方法来做到这一点,而无需手动逐行复制和粘贴?


当前回答

您当然可以通过单个复制/粘贴(使用块模式选择)完成所有这些操作,但我猜这不是您想要的。

如果你想用Ex命令来做这个

:5,8del | let l=split(@") | 1,4s/$/\=remove(l,0)/

将会改变

work it 
make it 
do it 
makes us 
harder
better
faster
stronger
~

into

work it harder
make it better
do it faster
makes us stronger
~

更新:有这么多赞的答案应该得到更彻底的解释。

在Vim中,您可以使用管道字符(|)来连接多个Ex命令,因此上面等价于

:5,8del
:let l=split(@")
:1,4s/$/\=remove(l,0)/

许多Ex命令接受一个行范围作为前缀参数——在上面的例子中,del前的5,8和s///前的1,4指定命令操作的行。

Del删除给定的行。它可以接受一个寄存器参数,但是当没有给出一个参数时,它将行转储到未命名的寄存器@”,就像在正常模式下删除一样。让l=split(@")然后使用默认分隔符:空白将被删除的行分割成一个列表。在被删除的行中有空格的输入上正常工作,例如:

more than 
hour 
our 
never 
ever
after
work is
over
~

我们需要指定一个不同的分隔符,以防止“work is”被分割成两个列表元素:let l=split(@","\n")。

最后,在替换s/$/\=remove(l,0)/中,我们用表达式remove(l,0)的值替换每行的结尾($)。Remove (l,0)改变列表l,删除并返回它的第一个元素。这让我们可以按照读取它们的顺序替换被删除的行。我们可以使用remove(l,-1)以相反的顺序替换被删除的行。

其他回答

要连接行块,您必须执行以下步骤:

去第三行,jj 进入可视块模式:CTRL-v 将光标锚定到行尾(对于不同长度的行很重要):$ 进入最后:CTRL-END 切块:x 转到第一行的末尾:kk$ 粘贴到这里:p

这个动作不是最好的(我不是专家),但它像你想要的那样工作。希望会有一个更短的版本。

以下是前提条件,所以这个技巧可以很好地工作:

起始块的所有行(在问题abc和def中的示例中)具有相同的XOR长度 起始块的第一行是最长的,你不关心中间的额外空格)XOR 起始块的第一行并不是最长的,你可以在末尾添加空格。

我觉得不要弄得太复杂。 我会设置virtualedit (:设置virtualedit =) 选择123块和下面所有的。 把它放在第一列之后:

abc    123
def    45
...    ...

并将其中的多重空格移除为1个空格:

:%s/\s\{2,}/ /g

您当然可以通过单个复制/粘贴(使用块模式选择)完成所有这些操作,但我猜这不是您想要的。

如果你想用Ex命令来做这个

:5,8del | let l=split(@") | 1,4s/$/\=remove(l,0)/

将会改变

work it 
make it 
do it 
makes us 
harder
better
faster
stronger
~

into

work it harder
make it better
do it faster
makes us stronger
~

更新:有这么多赞的答案应该得到更彻底的解释。

在Vim中,您可以使用管道字符(|)来连接多个Ex命令,因此上面等价于

:5,8del
:let l=split(@")
:1,4s/$/\=remove(l,0)/

许多Ex命令接受一个行范围作为前缀参数——在上面的例子中,del前的5,8和s///前的1,4指定命令操作的行。

Del删除给定的行。它可以接受一个寄存器参数,但是当没有给出一个参数时,它将行转储到未命名的寄存器@”,就像在正常模式下删除一样。让l=split(@")然后使用默认分隔符:空白将被删除的行分割成一个列表。在被删除的行中有空格的输入上正常工作,例如:

more than 
hour 
our 
never 
ever
after
work is
over
~

我们需要指定一个不同的分隔符,以防止“work is”被分割成两个列表元素:let l=split(@","\n")。

最后,在替换s/$/\=remove(l,0)/中,我们用表达式remove(l,0)的值替换每行的结尾($)。Remove (l,0)改变列表l,删除并返回它的第一个元素。这让我们可以按照读取它们的顺序替换被删除的行。我们可以使用remove(l,-1)以相反的顺序替换被删除的行。

样本数据与rampion的相同。

:1,4s/$/\=getline(line('.')+4)/ | 5,8d

有很多方法可以做到这一点。我将使用以下两种方法中的任何一种来合并两个文本块。

假设第一个块在第1行,第二个块从第10行开始,游标的初始位置在第1行。

(\n表示按回车键。)

1. abc
   def
   ghi        

10. 123
    456
    789

与宏使用命令:复制,粘贴和连接。

y \ npkJjq2@a10G3dd qaqqa: + 9

使用宏命令在第n行号移动一行并连接。

qcqqc: 10 m。\ nkJjq2@c