Vim是一个文本编辑器,也就是说你的大部分Vimscript代码的作用都是操作文本。Vim对正则表达式有着很强的支持,但是和其他的功能一样,这里也有一些陷阱。
把下面的文本输入到缓冲区:
max = 10
print "Starting"
for i in range(max):
print "Counter:",i
print "Done"
这就是我们要用来对Vimscript进行正则实验的文本。
我会假设你已经有了基本的正则知识。如果你不知道正则表达式的话,你需要暂时停住,然后去阅读Zed Shaw写的《Learn Regex the Hard Way》,读完之后再继续回到这里。
在我们开始之前,先需要打开高亮搜索的设置,这样我们就能够很清楚的看到自己在干什么。运行下面的命令:
:set hlsearch incsearch
hlsearch用来告诉Vim去高亮文件里所有匹配的文本,incsearch告诉vim在你输入搜索表达式的时候进行增量匹配,也就是在你还在输入的时候就开始进行匹配。
把光标放在文件的开始处,然后运行下面的命令:
/print
在你输入每个字符的时候,vim就从第一行开始进行高亮显示了。当你输入回车键来执行搜索的时候,所有的匹配到“pring”的实例都会被高亮显示,然后你的光标会被移动到接下来第一个匹配上的文本。
现在运行下面的命令:
:execute "normal! gg/print \"
首先,光标会移动到文本的开始处,然后搜索“print”,并让光标停留在第一个匹配的地方。这个是通过:execute "normal! ..."来实现的,这个我们之前就见过的。
如果要移动到第二个匹配的结果上去,只需要在后面再加上命令即可。运行下面的命令:
:execute "normal! gg/print\n"
Vim会把光标移动到第二个匹配的文本上去(并且所有匹配的文本都高亮显示)。
现在我们再反向操作,运行下面的命令:
:execute "normal! G?print\"
这次我们用G来移动到文本的末尾,然后用?来进行反向搜索。
这些搜索的命令相信你已经很熟悉了——我们曾多次用它们来讲解:execute "normal! ...的用法,因为它可以让你在Vimscript代码里做任何可以在vim里做的事情。
/和?命令的参数是正则表达式,不仅仅只是字符串。运行下面的命令:
:execute "normal! gg/for .+ in. +:\"
这次vim会抱怨说找不到要搜索的字符串!我前面告诉过你Vim的搜索是支持正则表达式的,但是是什么原因导致搜索不出来呢?运行下面的命令:
:execute "normal! gg/for .\\+ in .\\+:\"
这次vim会高亮for语句,这正是我们所期望的。花几分钟的时间来看看想想这个命令和之前到底有什么变化呢。记住execute要的只是一个字符串。
我们为什么要像上面那样来写正则表达式的命令呢,主要有两个原因:
你可以通过只在vim里用更简单的方式来使用它。运行下面的命令:
/print .\+
你可以看到+也起作用了。双斜杠只是在需要把把正则以字符串的方式传递给execute的时候使用。
我们之前已经提到了,vim运行你用单引号来定义一个“字符串常量”,即是所有的字符都当作原形处理。例如,字符串“a\n\b”就是代表四个字符。
那么在正则表达式里可以用字符串常量来避免要输入双斜杠吗?仔细考虑一下,这个问题的答案比我们想象的要复杂那么一点点。
运行下面的命令(注意单引号和单反斜杠):
:execute 'normal! gg/for .\+ in .\+:\'
Vim会把光标移动到文本的开始处,但是并不会移动到第一个匹配的文本。这是你所期望的吗?
这个命令不会起作用是因为我们需要\
但是,并不是一点都不能用的。还记得vim里是允许进行字符串拼接的吗,所以对于较长的命令,我们可以把它分割成更加容易阅读的部分。运行下面的命令:
:execute "normal! gg". '/for .\+ in .\+:' . "\"
这个命令先把三个字符串拼接起来,然后一起传给execute来执行,这样就允许我们把正则部分的字符串用字符串常量来表示,而一般字符串这直接表示。
你也许还在想Vimscript的4种不同模式的解析方式,以及它会同你在Python,Perl,Ruby等语言里学到的正则的差别。如果你想知道的比较全面的话,你可以去阅读以下文档,如果只是想简单了解的话,就借着往下读。
运行下面的命令:
:execute "normal! gg" .'/\vfor .+ in .+:' . "\"
这次我们再次把命令后面的部分分割成字符串常量,并且这次我们的正则则是以“\v”开头的。这个会告诉vim来用它的“very magic”模式来解析,这个模式和你在其他编程语言里用到的很相似。
如果你的正则是以“\v”开始的话,那么你就再也不需要担心vim的其他三种正则表达式的模式了。