Vimscript编程指南

基本正则表达式

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要的只是一个字符串。

我们为什么要像上面那样来写正则表达式的命令呢,主要有两个原因:

  • 首先,execute的参数是字符串,所以我们需要用双斜杠来表示单斜杠。
  • 其次,vim有4种不同的模式来解析正则表达式!默认的模式是需要在+号前面带斜杠,来表示后面有一个或者多个字符,而不是表示字符“+”。

你可以通过只在vim里用更简单的方式来使用它。运行下面的命令:


     /print .\+

你可以看到+也起作用了。双斜杠只是在需要把把正则以字符串的方式传递给execute的时候使用。

字符串常量

我们之前已经提到了,vim运行你用单引号来定义一个“字符串常量”,即是所有的字符都当作原形处理。例如,字符串“a\n\b”就是代表四个字符。

那么在正则表达式里可以用字符串常量来避免要输入双斜杠吗?仔细考虑一下,这个问题的答案比我们想象的要复杂那么一点点。

运行下面的命令(注意单引号和单反斜杠):


     :execute 'normal! gg/for .\+ in .\+:\'

Vim会把光标移动到文本的开始处,但是并不会移动到第一个匹配的文本。这是你所期望的吗?

这个命令不会起作用是因为我们需要\被转义成一个真正的换行符来让搜索的命令执行。因为我们用的是字符串常量,这个字符串就相当如在vim里直接输入“/for .+ in: .+:\”这个字符串,显然这不是我们想要的。

但是,并不是一点都不能用的。还记得vim里是允许进行字符串拼接的吗,所以对于较长的命令,我们可以把它分割成更加容易阅读的部分。运行下面的命令:


     :execute "normal! gg". '/for .\+ in .\+:' . "\"

这个命令先把三个字符串拼接起来,然后一起传给execute来执行,这样就允许我们把正则部分的字符串用字符串常量来表示,而一般字符串这直接表示。

更加不可思议的

你也许还在想Vimscript的4种不同模式的解析方式,以及它会同你在Python,Perl,Ruby等语言里学到的正则的差别。如果你想知道的比较全面的话,你可以去阅读以下文档,如果只是想简单了解的话,就借着往下读。

运行下面的命令:


     :execute "normal! gg" .'/\vfor .+ in .+:' . "\"

这次我们再次把命令后面的部分分割成字符串常量,并且这次我们的正则则是以“\v”开头的。这个会告诉vim来用它的“very magic”模式来解析,这个模式和你在其他编程语言里用到的很相似。

如果你的正则是以“\v”开始的话,那么你就再也不需要担心vim的其他三种正则表达式的模式了。

练习

  • 仔细阅读:help magic。
  • 阅读:help pattern-overview,看看vim支持那些正则表达式。在字元的地方停止。
  • 阅读:help match。试试:match Error /\v../命令。
  • 编辑你的vimrc文件,添加一个映射,用它来把行尾的空格作为错误来高亮显示。一个不错的选择是用w作为快捷键。
  • 添加另外一个映射用来删除上面匹配到的文本。
  • 添加一个normal模式下的影视,使得你在开始搜索的时候自动帮你输入\v。如果你忘记了怎么实现,你只要记住vim的映射很简单,你只要告诉它当你在使用映射的时候是需要输入什么就好了。
  • 把hlsearch和incsearch选项添加到你的vimrc文本里,根据你的需要去设置它们的值。
  • 阅读:help nohlsearch。记住,这是一个命令,并且不是hlsearch的关闭状态!
  • 添加一个映射,实现停止上一个搜索的高亮显示。