我想合并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
有没有一种很好的方法来做到这一点,而无需手动逐行复制和粘贴?
我想合并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
有没有一种很好的方法来做到这一点,而无需手动逐行复制和粘贴?
当前回答
我将使用复杂重复:)
鉴于这种:
aaa
bbb
ccc
AAA
BBB
CCC
将光标放在第一行,按下以下命令:
qa}jdd''pkJxjq
然后按下@a(随后可以使用@@),需要多少次就按多少次。
你应该得到:
aaaAAA
bbbBBB
cccCCC
(加上换行符。)
解释:
Qa开始记录一个复杂的重复 }跳转到下一个空行 JDD删除下一行 回到上次跳跃前的位置 P将删除的行粘贴到当前行下面 kJ将当前行附加到前一行的末尾 x删除J在合并行之间添加的空格;如果你需要空间,你可以省略这个 看下一行 Q结束复杂的重复记录
在此之后,您可以使用@a运行存储在a中的复杂重复,然后您可以使用@@重新运行上次运行的复杂重复。
其他回答
要连接行块,您必须执行以下步骤:
去第三行,jj 进入可视块模式:CTRL-v 将光标锚定到行尾(对于不同长度的行很重要):$ 进入最后:CTRL-END 切块:x 转到第一行的末尾:kk$ 粘贴到这里:p
这个动作不是最好的(我不是专家),但它像你想要的那样工作。希望会有一个更短的版本。
以下是前提条件,所以这个技巧可以很好地工作:
起始块的所有行(在问题abc和def中的示例中)具有相同的XOR长度 起始块的第一行是最长的,你不关心中间的额外空格)XOR 起始块的第一行并不是最长的,你可以在末尾添加空格。
您当然可以通过单个复制/粘贴(使用块模式选择)完成所有这些操作,但我猜这不是您想要的。
如果你想用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
下面是我的做法(把光标放在第一行上):
qama:5<CR>y$'a$p:5<CR>dd'ajq3@a
你需要知道两件事:
第二组的第一行开始的行号(在我的例子中是5),以及 每组中的行数(在我的例子中是3)。
事情是这样的:
Qa将下一个q之前的所有内容记录到a中的“缓冲区”中。 Ma在当前线上创建了一个标记。 :5<CR>进入下一组。 Y $ Yanks剩下的线。 'a返回之前设置的标记。 $p粘贴到行尾。 :5<CR>返回第二组的第一行。 Dd删除它。 ’a回到了起点。 Jq走下一行,停止录制。 3@a重复每一行的操作(在我的例子中是3行)
正如在其他地方提到的,块选择是可行的方法。但是你也可以使用以下的任何变体:
:!5 .尾部-n - 6% |粘贴-d '\0' % - |头部-n
此方法依赖于UNIX命令行。创建粘贴实用程序是为了处理这种行合并。
PASTE(1) BSD General Commands Manual PASTE(1)
NAME
paste -- merge corresponding or subsequent lines of files
SYNOPSIS
paste [-s] [-d list] file ...
DESCRIPTION
The paste utility concatenates the corresponding lines of the given input files, replacing all but the last file's newline characters with a single tab character,
and writes the resulting lines to standard output. If end-of-file is reached on an input file while other input files still contain data, the file is treated as if
it were an endless source of empty lines.