Vim是一个文本编辑器,这意味着大量的Vimscript代码将专注于处理文本。 Vim对正则表达式有着强大的支持,尽管一如既往地也有着一些坑。
把下面的文本打到缓冲区中:
~~~
max = 10
print "Starting"
for i in range(max):
print "Counter:", i
print "Done"
~~~
这个就是我们将用来测试Vimscript的正则支持的文本。它恰好是Python代码,但不要担心你看不懂Python。 它只是一个例子。
我会假定你懂得基本的正则表达式。如果你不懂, 你应该暂停阅读本书并开始阅读Zed Shaw的[Learn Regex the Hard Way](http://regex.learncodethehardway.org/)。 (译注:暂无中文版,也可选择别的书,或者just Google it) 在你看完后再继续。
## 高亮
在开始之前,先花点时间讲讲搜索高亮,这样我们可以让匹配的内容更明显。
~~~
:set hlsearch incsearch
~~~
`hlsearch`让Vim高亮文件中所有匹配项,`incsearch`则令Vim在你正打着搜索内容时就高亮下一个匹配项
## 搜索
移动你的光标到文件顶部并执行下面命令:
~~~
/print
~~~
当你逐字母敲打时,Vim开始在第一行高亮它们。当你按下回车来进行搜索时,高亮_所有_的`print`, 同时移动你的光标到下一处匹配。
现在尝试执行下面的命令:
~~~
:execute "normal! gg/print\<cr>"
~~~
这将移动到文件顶部并开始搜索`print`,带我们到第一处匹配。 用的是我们前一章看过的`:execute "normal! ..."`语法。
要到达文件中的第二处匹配,你仅需在命令的结尾加一点别的。执行这个命令:
~~~
:execute "normal! gg/print\<cr>n"
~~~
Vim将移动光标到缓冲区中的第二个`print`(同时高亮所有匹配)。
让我们尝试从反方向开始。执行这个命令:
~~~
:execute "normal! G?print\<cr>"
~~~
这次我们用`G`移动到文件结尾并用`?`来反向搜索。
所有的搜索命令应该已经烂熟于心 —— 我们在让你习惯`:execute "normal! ..."`惯用法时已经反复练习过, 因为它让你在Vimscript代码中能够做日常在Vim里做的事。
## 魔力(Magic)
`/`和`?`命令能接受正则表达式,而不仅仅是普通字符。执行下面命令:
~~~
:execute "normal! gg/for .+ in .+:\<cr>"
~~~
Vim抱怨说找不到模式!我告诉过你Vim支持正则搜索,所以为何如此?试试下面命令:
~~~
:execute "normal! gg/for .\\+ in .\\+:\<cr>"
~~~
这次Vim高亮"for"循环,如我们一开始所指望的。在继续阅读之前,花一分钟来想想为何如此。 记住`execute`接受一个字符串。
答案在此:我们需要这样写命令的原因有二:
* 首先,`execute`接受一个字符串,在调用`normal!`命令时,双反斜杠将转换成单反斜杠。
* Vim有四种不同的解析正则表达式的"模式"! 默认模式下需要在`+`前加上一个反斜杠来让它表示"一或多个之前的字符"而不是"一个字面意义上的加号"。
直接在Vim里执行搜索,你很容易就注意到它们的不同,输入下面的命令并按下回车:
~~~
/print .\+
~~~
现在你可以看到`\+`的魔力了。双反斜杠仅仅在把模式作为字符串传递给`execute`时才需要。
## 字面量字符串
正如我们在字符串那一章提到的,Vim允许你使用单引号来定义可以直接传递字符的字面量字符串。 比如,字符串`'a\nb'`有四个字符长。
我们可以使用字面量字符串来避免频繁敲打双重反斜杠吗? 先思考这个问题一两分钟,毕竟答案恐怕比你所认为的要更复杂一些。
试试执行下面的命令(注意这次的单引号和单反斜杠):
~~~
:execute 'normal! gg/for .\+ in .\+:\<cr>'
~~~
Vim带你到文件的顶部却不再移动到第一个匹配的地方。你猜对了吗?
命令之所以不能工作,是因为我们需要模式中的`\<cr>`被转义成回车,来启动搜索。 因为我们用的是字面量字符串,它并不等价于平常在Vim里键入`/for .\+ in .\+:\<cr>`, 显然这是无法工作的。
别怕,方法还是比困难多!不要忘了Vim允许字符串连接,所以可以将命令分割成容易理解的一小段。 执行下面的命令:
~~~
:execute "normal! gg" . '/for .\+ in .\+:' . "\<cr>"
~~~
这种方法可以在传递给`execute`之前把三小段字符串连接起来, 而且我们可以为正则使用字面量字符串并为其他的使用一般的字符串。
## 更多的魔力(Very Magic)
你可能会好奇Vimscript的四种不同的正则解析模式和它们跟Python,Perl或Ruby中的正则表达式有何不同。 你可以阅读它们的文档,如果你乐意。不过如果你只想找到一种简单科学的解决办法,请继续读下去。
执行下面的命令:
~~~
:execute "normal! gg" . '/\vfor .+ in .+:' . "\<cr>"
~~~
我们又一次把正则表达式放在单独的字面量字符串里,而这次我们用`\v`来引导模式。 这将告诉Vim使用它的"very magic"正则解析模式,而该模式就跟其他语言的非常相似。
如果你以`\v`开始你的所有正则表达式,你就不用再纠结Vimscript另外三种疯狂的正则模式了。
## 练习
认真阅读`:help magic`。
阅读`:help pattern-overview`来看看Vim支持的正则类型。在看到character classes时停下来。
阅读`:help match`。尝试手动执行几次`:match Error /\v.../`。
在你的`~/.vimrc`文件中加入使用`match`来高亮多余的空白为错误的映射。建议使用`<leader>w`。
加入另一个映射来清除匹配项(比如`<leader>W`)。
加入一个normal模式下的会在进行搜索时自动插入`\v`的映射。 如果你卡在这个练习上,不要忘了Vim的映射是非常简单的,你只需要告诉它把映射键转换成哪些键。
在你的`~/.vimrc`文件中加入`hlsearch`和`incsearch`选项,随你所欲地设置它。
阅读`:help nohlsearch`。注意这是一个_命令_并且_不是_`hlsearch`的"off mode"。
在你的`~/.vimrc`文件中加入消除最后一次搜索的匹配项的高亮的映射。
- 前言
- 鸣谢
- 预备知识
- 打印信息
- 设置选项
- 基本映射
- 模式映射
- 精确映射
- Leaders
- 编辑你的Vimrc文件
- Abbreviations
- 更多的Mappings
- 锻炼你的手指
- 本地缓冲区的选项设置和映射
- 自动命令
- 本地缓冲区缩写
- 自动命令组
- Operator-Pending映射
- 更多Operator-Pending映射
- 状态条
- 负责任的编码
- 变量
- 变量作用域
- 条件语句
- 比较
- 函数
- 函数参数
- 数字
- 字符串
- 字符串函数
- Execute命令
- Normal命令
- 执行normal!
- 基本的正则表达式
- 实例研究:Grep 运算符(Operator),第一部分
- 实例研究:Grep运算符(Operator),第二部分
- 实例研究:Grep运算符(Operator),第三部分
- 列表
- 循环
- 字典
- 切换
- 函数式编程
- 路径
- 创建一个完整的插件
- 旧社会下的插件配置方式
- 新希望:用Pathogen配置插件
- 检测文件类型
- 基本语法高亮
- 高级语法高亮
- 更高级的语法高亮
- 基本折叠
- 高级折叠
- 段移动原理
- Potion段移动
- 外部命令
- 自动加载
- 文档
- 发布
- 还剩下什么?