假设我有一个文件包含:
xxx
yyy
zzz
和另一个文件:
kkk
qqq
ppp
我想获得:
xxxkkk
yyyqqq
zzzppp
在 Vim 中可以通过一些命令实现这一点吗? (我尝试过使用 VISUAL BLOCK 但没有成功)。
在我的特殊情况下,我有两个大文件,其中有很多行要粘贴,因此答案也可能是一些 shell 命令,但我想知道是否有办法在同一个文件中执行此操作。
答案1
从命令行,你可以尝试
paste -d '\0' file1 file2 > file3
这正是你想要的。
Visual Block 模式vim
也非常适合这项任务。你确定你做对了吗?你应该
- 进入视觉块模式
- 选择文本并按下
y
进行拉取 - 转到另一个文件,在要粘贴数据的左上角(最后一个
x
),然后按p
。
答案2
编辑的时候直接做就可以了file1
。在 vim 中输入:
要切换到的内容。command mode
然后输入:
%!paste -d '' - file2
答案3
这是一种仅使用 Vim 在同一文件中完成此操作的方法。
它涉及一些键映射。当我想用简单的文本将几个列表排列成类似表格的结构时,我想到了这个。
这依赖于}键(右花括号)跳过段落边界。 (大括号是镜像的,顺便说一句:{跳到文件顶部并}到最后。)
所以...假设你有一个像这样的数据文件(这假设 line# 的打开方式为:设置nu):
+---------------
| 1 xxx (cursor on line#1)
| 2 yyy
| 3 zzz
| 4
| 5 kkk
| 6 qqq
| 7 ppp
+---------------
重要的是,第 4 行是空行(没有空格),我稍后会解释原因。
执行以下命令地图命令:
:map q mw}jdd'wpkJj
这会将“q”键绑定到一个 12 个字符的程序,我将在下面详细介绍该程序。
当你点击“q”时,它将执行该程序;请注意,从第 1 行开始的光标现在位于下一行,准备再次点击“q”。您可能已经注意到“xxx kkk”之间有一个空格字符;如果您不想要,请参阅“额外空间角色怎么样?”下面,接近尾声了。
+---------------
| 1 xxx kkk
| 2 yyy (cursor on line #2)
| 3 zzz
| 4
| 5 qqq
| 6 qqq
| ~
+---------------
以下是映射的细分:
:map q mw}jdd'wpkJj
^
冒号让您进入命令模式,以便我们可以发出“map”命令。
:map q mw}jdd'wpkJj
^^^^^
地图 q将 q 与以下字符序列绑定。请注意,“q”只是我常用的“映射到”键;您可以使用其他键。默认小写q映射为开始宏录制;因为我很少(从不?)使用我发现“q”对于一次性实用宏更有帮助。您还可以使用大写 Q(例如地图 Q)或 fnct 键等。
现在,每当您按“q”(在导航模式下)时,vim 都会执行这一系列击键:
mw}jdd'wpkJj
当然,这看起来完全是胡言乱语,所以我将逐个操作(用下面的^^)将其分解,以便更容易地了解正在发生的事情。
mw}jdd'wpkJj
^^
这兆瓦标记一个命名位置,这里的名称是“w”。我默认使用“w”(我认为这是我的“工作位置”。任何命名位置,从 az 都可以,只要你保持一致。
当我们想要将光标返回到这一行。
mw}jdd'wpkJj
^
这里我们有右卷发}它将光标向下跳转到下一个段落边界;换句话说,这会将光标移动到下一个空行,即我们示例中的第 4 行。 (这就是为什么第 4 行应该是空行;没有空格,否则}不会将其视为边界。)
mw}jdd'wpkJj
^
这j向下一行;这是老式的 vi“hjkl”导航。您也可以在这里使用向下箭头,我发现“j”更容易阅读,也更易于使用(因为箭头键在各种品牌的笔记本电脑和台式机键盘之间并不总是位于同一位置,但是“hjkl” " 保证始终位于任何 QWERTY 键盘主行的右侧(这有助于我的打字速度)。
无论如何,此时光标位于第 5 行。
+---------------
| 1 xxx
| 2 yyy
| 3 zzz
| 4
| 5 kkk (cursor on line#5)
| 6 qqq
| 7 ppp
+---------------
mw}jdd'wpkJj
^^
这DD是“删除行”编辑命令,因此它删除当前行,即带有“kkk”的第5行。删除该行还会将其放入默认的粘贴缓冲区中,我们将使用该漏洞将“kkk”带回我们想要的第 1 行“xxx”旁边的位置。
mw}jdd'wpkJj
^^
这'w(单引号 w)序列将光标跳回到“w”的书签,这将光标放在第 1 行。
mw}jdd'wpkJj
^
小写的“p”将当前的默认缓冲区(您可能还记得,带有“kkk”)放在光标后面。由于缓冲区包含以前的第 5 行内容,因此我们的文件现在大致如下所示:
+---------------
| 1 xxx
| 2 kkk (cursor on line#2, after the freshly restored "kkk")
| 3 yyy
| 4 zzz
| 5
| 6 qqq
| 7 ppp
+---------------
请注意“kkk”如何成为第 2 行。 (我无法轻易说明光标所在的位置...它实际上应该位于第 2 行的开头)。
我们已经很接近了,但还没有完全实现......
mw}jdd'wpkJj
^^
小写的k将光标跳到第 1 行(再次“hjkl”导航),然后大写J将下一行连接到当前行,使我们的文件看起来像这样(光标仍在第 1 行,在 x 和 k 之间):
+---------------
| 1 xxx kkk (cursor on line #1, between 'xxx' and 'kkk')
| 2 yyy
| 3 zzz
| 4
| 5 qqq
| 6 ppp
+---------------
mw}jdd'wpkJj
^
最后j再次是“hjkl”导航,它将光标向下移动到第 2 行,这很方便,因为这是我们要应用的下一行q到。
不管怎样,它看起来像这样:
+---------------
| 1 xxx kkk
| 2 yyy (cursor on #2)
| 3 zzz
| 4
| 5 qqq
| 6 ppp
+---------------
如果你再次点击“q”,它将看起来像这样(注意光标位于第 3 行)。
+---------------
| 1 xxx kkk
| 2 yyy qqq
| 3 zzz (cursor on #3)
| 4
| 5 ppp
+---------------
冲洗并根据需要重复。我发现这对于较长的列表很方便,因为它可以让我(相当)轻松地构建列。
这是一个更长的例子。在第 7 行添加一个空行会导致“ggg”首先堆叠在下一列中。到达“lll”后,将光标跳回第 1 行(左卷曲,{,效果很好),然后继续输入“mmm”。如果您认为不太喜欢它的排列方式,请按住你(撤消)一点并调整“边界”线的位置,然后重新开始。
这是一件比费力去解释更容易实现的事情。虽然我不认为我会用它来连接数千行,但我发现它对于数十行甚至数百行很方便。
+----------:---------------------------
| before : after
+----------:---------------------------
| 1 aaa : 1 aaa ggg mmm sss yyy
| 2 bbb : 2 bbb hhh nnn ttt zzz
| 3 ccc : 3 ccc iii ooo uuu
| 4 ddd : 4 ddd jjj ppp vvv
| 5 eee : 5 eee kkk qqq www
| 6 fff : 6 fff lll rrr xxx
| 7 :-------------------------
| 8 ggg
| 9 hhh
| 10 iii
| 11 jjj
| 12 kkk
| 13 lll
| 14 mmm
| 15 nnn
| 16 ooo
| 17 ppp
| 18 qqq
| 19 rrr
| 20 sss
| 21 ttt
| 22 uuu
| 23 vvv
| 24 www
| 25 xxx
| 26 yyy
| 27 zzz
+----------
额外空间角色怎么样?
连接命令的部分行为是它在连接的行之间放置一个空格。
如果你不这样做想“xxx kkk”之间有一个空格,您可以
将删除命令 (x) 添加到字符串中:
simple join (space char): :map q mw}jdd'wpkJj
join + x (kills space): :map q mw}jdd'wpkJxj
join w/comma: :map q mw}jdd'wpkJR,^[j
“join + x”通过使用X就在我们将两条线连接在一起之后。 X在导航模式下,删除光标所在的任何字符,在本例中是有问题的空格字符。
“join w/comma”用逗号替换空格。这基本上是相同的,但我们将逐步完成最后一部分,它与前面的示例略有不同。
:map q mw}jdd'wpkJR,^[j
^
这右让我们进入编辑模式(特别是替换模式,这将覆盖我们输入的任何字符)。
:map q mw}jdd'wpkJR,^[j
^
这,从字面上键入一个逗号,这会覆盖该点上有问题的空格。
:map q mw}jdd'wpkJR,^[j
^^
进而^[发出转义字符信号,该字符将离开编辑模式并使我们返回导航模式。
现在我们已经准备好决赛了j带我们到下一行。
要映射转义字符,您需要按 ^Q (windows) 或 ^V (linux & unix),然后按 Esc 键(如果不这样做,Esc 字符将中止命令,您会想知道为什么您的映射可能很复杂定义就消失了)。以下是您必须输入的序列才能将其输入到 Windows 上的 Vim 中:
:map q mw}jdd'wpkJR,<Ctr-Q><Esc>j
所以。 Vim 可能有几十种方法可以做到这一点。
当“字段”分隔符很重要时,我通常在每行的末尾放置一个简单的唯一序列,并进行全局搜索和替换,继续按照我想要的方式连接列,然后替换所有以获得我想要的特定分隔符。
无论如何,这只是一个例子。我希望你觉得这很有趣。