我想在Vim中合并两行线,即取线n..m
并将其附加到lines a..b
。如果您喜欢伪代码说明:[a[i] + b[i] for i in min(len(a), len(b))]
例:
abc
def
...
123
45
...
应该成为
abc123
def45
有没有一种好的方法,而无需手动进行复制和粘贴?
[a[i] + b[i] for i in min(len(a), len(b))]
我想在Vim中合并两行线,即取线n..m
并将其附加到lines a..b
。如果您喜欢伪代码说明:[a[i] + b[i] for i in min(len(a), len(b))]
例:
abc
def
...
123
45
...
应该成为
abc123
def45
有没有一种好的方法,而无需手动进行复制和粘贴?
[a[i] + b[i] for i in min(len(a), len(b))]
Answers:
您当然可以通过单个复制/粘贴(使用块模式选择)来完成所有这些操作,但是我想那不是您想要的。
如果您只想使用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
before del
和the 1,4
before s///
指定命令在其上进行操作的行。
del
删除给定的行。它可以接受一个寄存器参数,但是当没有给出时,它会将行转储到未命名的寄存器中,@"
就像在普通模式下删除一样。 let l=split(@")
然后使用默认的定界符:空格将删除的行拆分为一个列表。要在删除的行中包含空格的输入上正常工作,例如:
more than
hour
our
never
ever
after
work is
over
~
我们需要指定其他定界符,以防止“工作成果”被分为两个列表元素:let l=split(@","\n")
。
最后,在替换中s/$/\=remove(l,0)/
,我们用$
expression的值替换每行()的结尾remove(l,0)
。 remove(l,0)
更改list l
,删除并返回其第一个元素。这使我们可以按照读取顺序替换已删除的行。相反,我们可以使用来以相反的顺序替换已删除的行remove(l,-1)
。
s/\s*$/
代替删除任何尾随空格s/$/
。
:sil5,8del | let l=split(@") | sil1,4s/$/\=remove(l,0)/ | call histdel("/", -1) | nohls
似乎更好,因为它可以在运行后清除搜索历史记录。而且它没有显示“ x更多/更少的行”消息,要求我按Enter。
:help range
,:help :d
,:help :let
,:help split()
,:help :s
,:help :s\=
,:help remove()
。
优雅而简洁的Ex命令解决的问题可以通过组合获得:global
,:move
和:join
命令。假设第一个行块在缓冲区的第一行开始,并且光标位于第二个块的第一行之前的行上,则命令如下。
:1,g/^/''+m.|-j!
有关此技术的详细说明,请参见我对类似问题“ Vim paste -d'的开箱即用行为?”。
E16: Invalid Range
-但仍然可以。当删除1,
它时,没有错误。
:move
和:join!
,也没有什么''
意思的范围参数(:help ''
),什么+
和-
意味着作为范围调节剂(:help range
)。谢谢!
sil!
在命令前添加命令来抑制错误消息。
要连接线段,您必须执行以下步骤:
jj
CTRL-v
$
CTRL-END
x
kk$
p
这项运动不是最好的运动(我不是专家),但它的工作原理就像您想要的那样。希望会有一个简短的版本。
这是必备条件,因此此技术效果很好:
abc
和中的示例中def
)的长度XOR相同abc
和def
长度相同而按需要进行。块选择将保留已删除文本的缩进,因此,如果在放置文本时光标位于短行上,则将这些行插入较长的字母之间;如果光标位于较长的字母上,则将空格插入到较短的字母之间一。
:%s/ \+/ /g
set ve=all
应该帮助,请参阅vimdoc.sourceforge.net/htmldoc/options.html#'virtualedit “
这是我的操作方式(光标放在第一行):
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)[Enter]
后:5
都必须按一次,否则将不起作用。
:norm qama:5<CR>y$'a$p:5<CR>dd'ajq3@a
但这似乎只能执行q
。
:let @a="ma:5^My$'a$p:5^Mdd'aj" | normal 4@a
,在其中^M
按CTRL-V然后按Enter键入字符。
如其他地方所述,块选择是必经之路。但是您也可以使用以下任何变体:
:!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.
我会使用复杂的重复:)
鉴于这种:
aaa
bbb
ccc
AAA
BBB
CCC
将光标放在第一行上,按以下命令:
qa}jdd''pkJxjq
然后根据需要多次按@a
(您可能随后使用@@
)。
您应该最终得到:
aaaAAA
bbbBBB
cccCCC
(加上换行符。)
说明:
qa
开始记录一个复杂的重复 a
}
跳到下一个空行
jdd
删除下一行
''
返回上一跳之前的位置
p
将已删除的行粘贴到当前行下
kJ
将当前行附加到上一行的末尾
x
删除在J
合并的行之间添加的空间;如果需要空间,可以忽略此
j
转到下一行
q
结束复杂的重复录音
之后,您将用于@a
运行存储在中的复杂重复a
,然后可以用于@@
重新运行上次运行的复杂重复。
x
与加盟x+2
?