我有一个这样的文本文件(在Windows上使用gVim)

foo bar baz quux 
corge grault garply 
waldo fred plugh 
[...150 more lines...]
xyzzy thud


我想在文件的每一行中添加一个数字。不使用:set number,而是按如下所示将数字添加为每行前面的文本,因此该数字是文件的一部分。

评论

awk可能是这项工作的工具。但是我在Windows上(叹气)。

已经在这里回答了,没关系:)

也许..或者这更笼统?

相似,但是我不知道什么是永久行号。其次,另一个问题是专门针对Windows上gVim的所有行(答案就是这样做),这是仅在普通vim中一个段落的简单编号列表。

好吧,我想post使用的是“永久”字样,它表示缓冲区将被修改,并且数字不是纯粹的视觉对象(与您相同)。在Windows上指定gvim的原因是避免使用外部实用程序,例如cat或nl,它们可以执行数字行,但通常在Windows上不可用(如OP从其对awk的评论中所表明的那样)。前两个解决方案是纯Vim。最后,所有行与一个参数仅是范围选择的问题。显然不是大问题。

#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. h后,您将位于第二列,而不是第一列。我将h替换为0,之后我认为您的解决方案应该很好。

– 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


向上一行并删除换行符,换行符是:。=命令的结果。