我有一个问题,我可以想到两种通用的解决方法,但是我都不知道每种方法的具体情况。

我要插入一个以“ 01”开头的数字。为简单起见,让我们为数字加上前缀。

方法1:手动选择所有具有相同Level的行。调用魔法,我很快就会学到。

方法2:编写一个搜索并替换,该替换将匹配具有给定级别的所有行,并且在每个匹配项中包括替换文本中的一个数字,该数字在每个匹配项中增加一个。

我在StackOverflow或其他Vim站点上也发现了类似的问题,但每个问题似乎都具有以下一个或多个问题:


插入当前行号,而不是插入一个任意的但递增的数字。
不对数字进行零补。 (这些都会导致错误E481: No range allowed。) />

评论

我能想到的最佳标签不存在:选择和范围,因此可以随时重新标签或创建这些标签之一。

这个插件不是解决您问题的完整解决方案,但是对于添加数字列非常有用:VisIncr。文档在这里。 FWIW。

#1 楼

与https://vi.stackexchange.com/a/818/227上的答案类似,您可以使用全局命令。

它可以指示vim搜索与模式匹配的行,然后在其上执行命令。

您希望将文本添加到以“ Level N:”开头的行之前,因此我们的全局命令可能是

:g/^Level \d:/{COMMANDS}


将替换命令(正则表达式替换)用于命令

命令更有趣。我通常喜欢用正则表达式替换类似的东西,因为它很容易使用变量。 >它的工作方式

在替换命令的替换部分可以是一个表达式。

我们要做的第一件事是将变量i设置为起始编号。我选择了1,但任何数字都可以。 let i = 1

然后运行全局命令,该命令将我们设置为在匹配的行上执行操作。 g/^Level \d:/

使用替换命令和let命令,让全局命令插入值并增加计数器。 s/^/\=printf("%02d ", i)/ | let i = i+1

替换命令的正则表达式查找^行的开头,并将其替换为表达式,我们的表达式将是格式化打印的结果。像C语言一样,vim的printf带有格式设置参数。 %02d意味着将参数转换为十进制数字d,至少占用2个空格2并填充0 0。有关详细信息和其他转换选项(包括浮点格式),请参见:help printf。我们给printf我们的计数变量i,第一次给我们01,第二次给我们02,以此类推。替换命令使用它来替换行的开头,从而有效地将printf的结果插入开头。 br />
请注意,我在d之后放置了一个空格:"%02d "。您没有在问题中提出要求(并且我没有看到示例输出),但我怀疑您想将数字与单词“ Level”分开。从给printf的字符串中删除空格,使插入的数字紧靠Level中的L。

最后,每次替换后let i = i + 1都会增加我们的计数器。通常可用于用任意功能数据替换与其他条件匹配的行的部分。与替换类似,我们将使用global进行匹配,但是将代替用户使用正则表达式替换正则表达式,而是执行一系列操作。

问题示例

:let i = 1 | g/^Level \d:/s/^/\=printf("%02d ", i)/ | let i = i+1


如何工作

使用的值与替代项非常相似(我们仍在使用printf格式化我们的数字以使其填充0 2位数字),但操作不同。我们构造了一个字符串,该字符串将“ normal!I”与我们的数据结合在一起,第一次将是“ normal!I01”,第二次将是“ normal!I02”,等等。操作就像在普通模式下一样。在此示例中,我们的常规命令是:help :exe,它将插入到行的开头。如果我们使用了normal,它将删除该行,而I将在匹配的行之后打开一个新行。就像您在正常模式下自己键入dd(或其他任何操作)一样。我们在o之后使用I来确保没有映射妨碍我们。请参阅!

然后插入的是我们的printf的值,如第一个使用替代的示例中一样。该方法比正则表达式更奇特,因为您可以执行normal之类的操作,该操作将转到文本:help :normal的开头,向前移动2个单词execute "normal! ^2wy" . i . "th$p",拉动直到第i个“ h”字符^,然后移至行尾2w,然后粘贴y" . i . "th。这几乎就像运行宏一样,但是实际上并没有用完寄存器,而是可以合并任何表达式中的字符串。我发现这非常强大。

每个级别都有自己的计数器的方法

您可能希望每个级别都有自己的计数器。如果您提前知道最大级别数,则可以执行以下操作(添加额外的代码以查找最大级别可能并不难,但是会使此答案变得太长。这会变得很长)。 br />
首先,让我们释放i,以防万一我们已经将其用作整数。我们无法将i转换为列表,我们必须以这种方式创建它。您在问题中显示了2,但假设其中有10个是有趣的。由于列表索引是基于0的,并且我不想像您的列表那样更正基于1的索引,因此我们将只创建足够的元素(11),并且永远不要使用0索引。 br />
接下来,我们需要一种获取级别编号的方法。幸运的是,替代函数也可以使用,因此我们将其命名为行并提取级别号$

因为我现在是11个p的列表(每个索引都是我们的级别),我们现在可以调整以上任一示例以使用此替换的结果:

通过替换命令:

:let i = 1 | g/^Level \d:/execute "normal! I" . printf("%02d ", i) | let i = i+1


通过常规命令:

:unlet! i


示例输入:

:let j = 0
:let i = []
:while j < 11 | let i += [1] | let j += 1 | endwhile


示例输出:

:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \(\d\):.*", "\=submatch(1)", "")) | s/^/\=printf("%02d ", i[ind])/ | let i[ind] += 1


评论


哇,非常百科。我只阅读了第一部分,感觉比过去几年我从中学到了更多关于Vim的知识。这种答案使Stack Exchange优于一般的问答站点,并且显示了具有Vim特定SE的好处。

–hippietrail
2015年4月30日,下午3:48

#2 楼

您可以通过录制宏来处理它。从原始文件开始,在第一个实例前添加数字。现在您要记录从这一点开始的动作。

01



yiw在寄存器q中启动宏/> qq/^Level 1<CR>P<C-A>A<space><esc>0yiwq搜索以“ Level 1”开头的行

qq在光标之前粘贴(包含您的数字)

/^Level 1<CR>递增数字P在数字后面插入空格

<C-A>移至开头

A<space><esc>取消当前数字

0结束宏

,然后使用yiw重复此宏。

评论


控件+ a吗?这样就可以选择Windows上Vim中的所有内容。

–hippietrail
2015年4月29日在2:43

它是Control + a。在vim中,它应该增加一个数字。如果您已将键绑定更改为执行Windows操作而不是执行Vim操作,则您将无法执行人们在此处发布的大多数操作。

–jecxjo
2015年4月29日在2:45

由于有人的无限智慧,Windows的Vim版本没有附带不同的绑定。我只是使用香草的现成绑定。我回想起(-:

–hippietrail
2015年4月29日在2:47



并非如此,我的Windows安装具有正常的vim绑定。您是否可能安装了其他人的vim版本?还是可以在“简易”模式下运行vim?我相信Windows会以普通和简易模式选项安装桌面图标。

–jecxjo
15年4月29日在2:50

不,这是因为Windows中的默认安装会加载mswin.vim。如果您创建自己的vimrc而不加载mswin.vim,则将获得正常的vim绑定。我为所有安装(Linux,Mac和Windows)保留一个vimrc,从不处理mswin.vim。有关此问题的更多信息,请参见stackoverflow.com/questions/289681/…

–jecxjo
2015年4月29日在2:53



#3 楼

您可以从https://stackoverflow.com/a/4224454/15934进行构建,以零填充您的数字。 ,我将使用一对函数和一个命令:

" A reminder: how to start numbers at the first line
:'<,'>s/^\s*\zs/\=(line('.') - line("'<")+1).'. '


然后,选择您的行并键入:PrependNumber(您将看到:'<,'>PrependNumber。命令采用可选参数:将在其之前插入数字的模式]

评论


但是line(“。”)的意思不是“使用当前行号”吗?那是我的问题1.我可以找到以前的答案。

–hippietrail
2015年4月29日在8:19

是的。这就是为什么我减去范围中第一行的行号。

–卢克·赫米特(Luc Hermitte)
15年4月29日在8:20

啊,好的,我还没有测试过,因为我什至不记得如何在Vim中输入脚本...必须首先阅读(-

–hippietrail
2015年4月29日在8:23

在Windows下,将代码复制粘贴到$ HOME / vimfiles / plugin / whatevernameyouwish.vim中。或者,如果您愿意(甚至是第一次),甚至是$ HOME / _vimrc(Windows文件名)。如果不确定计算机上的$ HOME是什么,请询问vim它认为它是什么->:echo $ HOME

–卢克·赫米特(Luc Hermitte)
2015年4月29日在8:27

如果vim脚本已正确安装在正确的目录({rtp} / plugin,或{rtp} / ftplugin / {filetype} / ftplugin(针对特定于文件类型的插件)中,则甚至不需要:source。 :source是我们十年半前不得不玩的东西。

–卢克·赫米特(Luc Hermitte)
2015年4月29日在8:35