我想在Vim中合并两个线块,即取n..m
行并将它们附加到行a..b
。如果您更喜欢伪代码说明:[a[i] + b[i] for i in min(len(a), len(b))]
示例:
abc
def
...
123
45
...
应该成为
abc123
def45
如果不手动复制和粘贴,有没有很好的方法呢?
答案 0 :(得分:881)
你当然可以通过一次复制/粘贴(使用块模式选择)完成所有这些,但我猜这不是你想要的。
如果您只想使用Ex命令
执行此操作:5,8del | let l=split(@") | 1,4s/$/\=remove(l,0)/
将转换
work it
make it
do it
makes us
harder
better
faster
stronger
~
到
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命令接受一系列行作为前缀参数 - 在上面的例子中,5,8
之前的del
和1,4
之前的s///
指定了哪些行命令操作。
del
删除给定的行。它可以采用寄存器参数,但是如果没有给出,它会将行转储到未命名的寄存器@"
,就像在正常模式下删除一样。 let 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)
以相反的顺序替换已删除的行。
答案 1 :(得分:55)
可以通过以下方式获得解决问题的优雅简洁的Ex命令
结合:global
,:move
和:join
命令。假设那个
第一个行块在缓冲区的第一行开始,而那个
光标位于紧靠第一行之前的行上
第二个块,命令如下。
:1,g/^/''+m.|-j!
有关所用技术的详细说明,请参阅我给的answer 问题“Vim paste -d ' ' behavior out of the box?”。
答案 2 :(得分:44)
要加入行块,您必须执行以下步骤:
jj
CTRL-v
$
CTRL-END
x
kk$
p
运动不是最好的运动(我不是专家),但它的运作方式与你想要的一样。希望会有更短的版本。
以下是先决条件,因此这项技术运作良好:
abc
和def
中的示例中)具有相同的长度 XOR 答案 3 :(得分:19)
这是我如何做到的(光标在第一行):
qama:5<CR>y$'a$p:5<CR>dd'ajq3@a
你需要知道两件事:
这是发生了什么:
qa
将q
中的所有内容记录到a
中的“缓冲区”中。ma
在当前行上创建标记。:5<CR>
转到下一组。y$
猛拉其余部分。'a
返回前面设置的标记。$p
贴在行尾。:5<CR>
返回第二组的第一行。dd
删除它。'a
返回商标。jq
下线一行,然后停止录音。3@a
重复每一行的动作(在我的情况下为3)答案 4 :(得分:8)
如其他地方所述,块选择是要走的路。但您也可以使用以下任何变体:
:!tail -n -6 % | paste -d '\0' % - | head -n 5
此方法依赖于UNIX命令行。创建了paste
实用程序来处理这种行合并。
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.
答案 5 :(得分:3)
样本数据与rampion的相同。
:1,4s/$/\=getline(line('.')+4)/ | 5,8d
答案 6 :(得分:3)
我不认为让它变得太复杂。
我只想在上面设置virtualedit
(:set virtualedit=all
)
选择块123以及下面的全部
把它放在第一栏之后:
abc 123
def 45
... ...
并删除1个空格之间的多个空格:
:%s/\s\{2,}/ /g
答案 7 :(得分:2)
我会使用复杂的重复:)
鉴于此:
aaa
bbb
ccc
AAA
BBB
CCC
将光标放在第一行的第一个“a”处,按以下键:
qq}jdd''$pkJj0q
然后根据需要多次按@q
(您可以随后使用@@
)。
你最终应该:
aaaAAA
bbbBBB
cccCCC
(加上换行符。)
答案 8 :(得分:1)
可以通过多种方式实现这一目标。我将使用以下两种方法中的任何一种合并两个文本块。
假设第一个块位于第1行,第二个块从第10行开始,光标的初始位置位于第1行。
(\ n表示按回车键。)
1. abc
def
ghi
10. 123
456
789
使用命令宏:复制,粘贴和连接。
使用命令使用宏qaqqa:+ 9Y \ npkJjq2 @ a10G3dd
在第n个行号处移动一行并加入。
qcqqc:10m。\ nkJjq2 @ c