如何在 Vim 中合并两个多行文本块? [英] How to merge two multi-line blocks of text in Vim?

查看:50
本文介绍了如何在 Vim 中合并两个多行文本块?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 Vim 中合并两行代码块,即取行 kl 并将它们附加到行 m通过n.如果你更喜欢伪代码解释:[line[k+i] + line[m+i] for i in range(min(l-k, n-m)+1)].

例如

abc定义...12345...

应该变成

abc123def45

有没有一种不用逐行手动复制和粘贴的好方法?

解决方案

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

如果您只想使用 Ex 命令执行此操作

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

会变身

工作做了做使我们更难更好的快点更强~

进入

加倍努力让它更好做得更快使我们更强大~

<小时>

更新:有这么多赞成票的答案值得更彻底的解释.

在Vim中,可以使用管道符(|)来链接多个Ex命令,所以上面等价于

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

许多 Ex 命令接受一系列行作为前缀参数 - 在上述情况下,del 之前的 5,81,4s/// 之前指定命令操作的行.

del 删除给定的行.它可以接受一个寄存器参数,但是当没有给出一个参数时,它会将这些行转储到未命名的寄存器 @",就像在正常模式下删除一样.let l=split(@") 然后将删除的行拆分为一个列表,使用默认分隔符:空格.要在已删除行中有空格的输入上正常工作,例如:

超过小时我们的绝不曾经后工作是超过~

我们需要指定一个不同的分隔符,以防止工作是"被分成两个列表元素:let l=split(@","\n").>

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

I’d like to merge two blocks of lines in Vim, i.e., take lines k through l and append them to lines m through n. If you prefer a pseudocode explanation: [line[k+i] + line[m+i] for i in range(min(l-k, n-m)+1)].

For example,

abc
def
...

123
45
...

should become

abc123
def45

Is there a nice way to do this without copying and pasting manually line by line?

解决方案

You can certainly do all this with a single copy/paste (using block-mode selection), but I'm guessing that's not what you want.

If you want to do this with just Ex commands

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

will transform

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
~


UPDATE: An answer with this many upvotes deserves a more thorough explanation.

In Vim, you can use the pipe character (|) to chain multiple Ex commands, so the above is equivalent to

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

Many Ex commands accept a range of lines as a prefix argument - in the above case the 5,8 before the del and the 1,4 before the s/// specify which lines the commands operate on.

del deletes the given lines. It can take a register argument, but when one is not given, it dumps the lines to the unnamed register, @", just like deleting in normal mode does. let l=split(@") then splits the deleted lines into a list, using the default delimiter: whitespace. To work properly on input that had whitespace in the deleted lines, like:

more than 
hour 
our 
never 
ever
after
work is
over
~

we'd need to specify a different delimiter, to prevent "work is" from being split into two list elements: let l=split(@","\n").

Finally, in the substitution s/$/\=remove(l,0)/, we replace the end of each line ($) with the value of the expression remove(l,0). remove(l,0) alters the list l, deleting and returning its first element. This lets us replace the deleted lines in the order in which we read them. We could instead replace the deleted lines in reverse order by using remove(l,-1).

这篇关于如何在 Vim 中合并两个多行文本块?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆