foo bar baz quux
corge grault garply
waldo fred plugh
[...150 more lines...]
xyzzy thud
我想在文件的每一行中添加一个数字。不使用
:set number
,而是按如下所示将数字添加为每行前面的文本,因此该数字是文件的一部分。#1 楼
以纯Vim格式::%s/^/\=line('.').". "
说明:
在替换部分中使用表达式非常强大,FWIW是vimscript的很好入门。
评论
如何在vimrc的键盘映射中添加这个非常有用的命令?
–cosmicraga
19年7月20日在8:26
进入vim帮助主题进行替换::help sub-replace-expression
–akurtser
19年9月1日13:00
#2 楼
Vim宏的一个优点是它们可以递归(它们可以调用自己):清除寄存器q:
qqq
将数字加到第一个行:
ggI1.
(不要忘记空格!)移回行首并开始录制宏:
0qq
复制号码:
yW
向下移动一行并粘贴数字:
+P
移回该行的开头并递增数字:
0<c-a>
移回该行的开头(因此宏在加倍时不会中断!):
0
调用一次宏,使其递归。此时,寄存器q中仍然没有任何内容,因此什么也不会发生:
@q
。保存宏:
q
再调用一次宏,观察火花飞扬!:
@@
然后宏将继续调用自身,直到到达文件末尾。
您可以对许多其他类似问题使用递归宏技巧,所以这是一个很好的认识。
如果由于某种原因不想使用递归宏,则可以省略第1步和第8步,并使用计数来运行宏多次,例如
100@q
将运行q
宏100次。评论
功能强大的东西,我向您鞠躬致敬。宏对我来说就像是黑魔法。
–roblogic
2015年2月11日在12:09
@ropata,宏只是(通常是)正常模式命令的序列。
– romainl
2015年2月11日下午13:37
@romainl我认为最好将其视为一系列击键。
–丰富
2015年2月11日下午13:47
@Rich,它可以是很多事情的序列,包括ex命令。
– romainl
2015年2月11日在21:34
@romainl是的,这就是为什么我认为最好将其视为击键。它会精确地播放您在键盘上键入的内容(包括您所说的ex命令),就像您手动键入所有内容一样。
–丰富
15年2月12日在9:46
#3 楼
我喜欢使用vim global命令来完成这样的任务。这适用于将迭代添加到行的开头或修改文本中的符号。它看起来比其他解决方案更为复杂,但是在您方便使用时,它是一种非常灵活的模式,并且无需过多考虑即可轻松进行修改。首先,选择范围(哪些行您要应用此)。我通常使用标记(例如,第一行使用
ma
,第二行使用mb
,但您也可以使用行号或可视选择),然后输入以下命令的修改(当前针对您的用例进行了调整):let i=1|'a,'bg/^/s/^/\=i.". "/|let i=i+1
解构
:let i=1
这将设置具有初始值的变量
i
。通常列表以1开头,所以我将i设置为1。 > 设置下一个命令的范围。我将从标记
a
转到标记b
,它将设置在列表的第一行和最后一行。|
这是全局命令。它在文件(或范围)中搜索给定的正则表达式,然后在匹配的每一行上执行其余命令行。我通过搜索“行的开头”来匹配每一行。如果您有类似
'a,'b
之类的文本,并且只想将这些标签放在
Item
前面,而忽略其他行,请改用g/Item/
或g/^Item/
(假设原义为Item文本)g/^/
这将执行正则表达式,以用
i
所连接的.
值替换行的开头。通常,您可以对任何内容执行此操作(例如,用数字替换标签Item
。)Item some txt
other text
Item second item
whatever
Item third
即使该栏启动了新命令,它也会设置第二条命令在全局命令中运行,而不是在完成全局操作之后运行。结果是我们在下一行由g处理之前增加
i
。这是另一个灵活性的地方。 i的修改可以是任何值(加2时,调用生成斐波那契数列的下一个元素的函数)。#4 楼
在所有行中添加数字可以使用
:%!nl -ba
或:%!cat -n
命令将数字添加到所有行中。在Windows上,必须安装Cygwin / MSYS已安装/ SUA。
将数字添加到选定的行
要仅为选定的行添加数字,请在可视模式(v和光标)中选择它们,然后在完成时-执行命令:
:%!nl
(忽略空行)或:%!cat -n
(包括空行)。要删除多余的空格,请在可视块(Ctrl + v)中选择它们,然后删除它们(x)。要在数字后添加一些字符(
.
,:
,)
),请在可视块(Ctrl + v)中选择它们,然后附加字符(A,键入字符,然后按Esc键。)评论
这与问题中给出的格式不同。但是,我喜欢该解决方案的简单性。
– Karl YngveLervåg
15年2月15日在9:27
@KarlYngveLervåg谢谢,将其包含在答案中。
– Kenorb
15年2月15日在22:12
#5 楼
romainl答案的修改::%s/^\(\d\+\. \)\?/\=line('.').". "
这不仅将添加行号,还将替换现有的行号。其中,如果您在中间插入一行,它将按预期方式对所有内容重新编号。
这可以通过替换任何数字后跟一个。在行的开头有一个新数字的空格。如果您有已经以该模式开头的行,则显然会中断,因此请谨慎使用。
添加的部分:
^
-行开始和一个空格\(
。 > 奖金提示:
要删除行号,可以使用相同的模式,将空白部分留空:
:%s/^\(\d\+\. \)\?//
#6 楼
I1. <esc>^qqyWjP^<C-a>q
这将对前两行进行编号,您可以按
@q
对后续的行进行编号(如果要对总共20行进行编号,请键入ex。18@q
)。解释:
I1. <esc> Number the first line
hqq Go back to the start of the line and start recording a macro
yWjP Copy the line number to the next line
^<C-a> Increment the next line's line number
q Finish recording
这样的好处是它不需要任何外部命令,例如,如果您在Windows上使用Vim,这将很有用。 br />
评论
输入1.
– Karl YngveLervåg
15年2月15日在9:26
@KarlYngveLervåg糟糕,这是一个错字。谢谢,修复它。
–门把手
15年2月15日在14:18
没问题。但是,您仍然没有更新说明。另外:在许多键盘上,^等待第二个字符,以便允许键入诸如^ a->â之类的组合。我仍然同意其最佳解决方案,但我认为也应提及这一点。
– Karl YngveLervåg
15年2月16日在10:48
#7 楼
我认为选择的答案是最好的,但是从多种多样的角度来看,我将使用外部程序提供替代方法::%!cat -n
这将过滤整个缓冲区(如
%
所示)通过外部程序cat
进行,其中-n
标志在输入的每一行前都添加了行号。适用于(可能)所有类似Unix的系统。请查阅
cat
以获得有关通过外部程序进行过滤的更多详细信息。评论
我意识到,问问者在Windows上使用gVim,所以该解决方案可能在那里不起作用。但是,我认为它仍然为其他人提供了一些学习的机会。
–tommcdo
2015年2月11日,14:28
如果您已安装msysgit并将其添加到PATH(IIRC是安装选项),则该解决方案也应在Windows上运行。
–马丁·图尔诺伊(Martin Tournoij)
2015年2月11日14:40
cat -n不是POSIX,但是nl是,所以它可能是一个更好的选择。
–muru
2015年2月11日14:43在
#8 楼
以下可能是一个有点棘手的解决方案(按Ctrl + v后将插入<和>之间的所有内容)::%normal :redir @"<Enter>:-=<Enter>:redir END<Enter>I<C-R>".<Tab><Esc>kdd
解构
:%normal {commands}
在范围指定的每一行上运行普通模式命令,在这种情况下,每行
:redir @"
重定向由ex命令到未命名的缓冲区。
:.=
是一个ex命令,可输出当前行号(不幸的是带有前一个换行符)
:redir END
停止重定向到未命名缓冲区。
I<C-R>".<Tab><Esc>
用插入未命名缓冲区的内容。
kdd
向上一行并删除换行符,换行符是:。=命令的结果。
评论
awk可能是这项工作的工具。但是我在Windows上(叹气)。已经在这里回答了,没关系:)
也许..或者这更笼统?
相似,但是我不知道什么是永久行号。其次,另一个问题是专门针对Windows上gVim的所有行(答案就是这样做),这是仅在普通vim中一个段落的简单编号列表。
好吧,我想post使用的是“永久”字样,它表示缓冲区将被修改,并且数字不是纯粹的视觉对象(与您相同)。在Windows上指定gvim的原因是避免使用外部实用程序,例如cat或nl,它们可以执行数字行,但通常在Windows上不可用(如OP从其对awk的评论中所表明的那样)。前两个解决方案是纯Vim。最后,所有行与一个参数仅是范围选择的问题。显然不是大问题。