分类: C/C++
2011-04-29 22:40:23
这里所说的多文件查询,是指在多个文件中查询指定的内容,即英文中所谓的Search in files,而不是查询文件。
Vim支持两种多文件查询,分别是:vimgrep和:grep,前者是内部查询,后者是外部查询。
所谓内部查询,是Vim内建的多文件查询功能,它的原理为将所有要查询的文件逐个打开,然后像使用/键查询那样查询这些文件的内容。它的优点是不需要任何设置即可在任何Vim支持的平台上运行,同时可以使用功能比较强大的Vim正则表达式,另外,对于非英文字符,只要Vim可以正确识别的,:vimgrep都可以正常查询。这种查询方式的缺点也很明显,由于是模拟逐个打开文件并查询,因此它的速度一般比较慢,对于像我这样动辄在包含有几百个文件的项目中搜索的情况,用:vimgrep是一种煎熬。
vimgrep的命令格式为:
:vim[grep][!] /{pattern}/[g][j] {file}
最基本的用例:
:vim /function demo/ *.php
即在当前目录下所有的php文件中查询"function demo",若希望在递归查询当前目录及其所有任何深度的子目录中的php文件,格式为:
:vim /function demo/ **/*.php
如果要同时在js文件中搜索,格式有两种:
:vim /function demo/ **/*.{php,js}
:vim /function demo/ **/*.php **/*.js
默认情况下,vim会在当前窗口中打开所有查询结果中的第一个,如果不希望这样,办法有两种:
:vim! /function demo/ **/*.{php,js}
:vim /function demo/j **/*.{php,js}
另外,缺省情况下,vimgrep查询时是否区分大小写受vim选项ignorecase控制,可以在查询表达式中使用\c表示忽略大小写,或者使用\C表示区分大小写:
:vim /\cfunction demo/ **/*.{php,js}
:vim /\Cfunction demo/ **/*.{php,js}
除j外,还有一个选项g。缺省情况下,即使一行中多次出现了查询表达式所匹配的内容,vim也会将其按一个查询结果返回;加上g选项后,vim会将这样的行当多个查询结果返回。
至于外部查询方式,是vim调用外部的查询工具进行多文件查询并获取其查询结果。这种查询方式的优点是给予用户最大的方便,以允许使用各自熟悉的查询工具完成工作。虽然其功能和速度取决于所调用的外部查询工具,但一般来说使用外部查询工具会比vimgrep速度快很多。其缺点是需要配置才能使用,并且不同的系统环境下所使用的外部查询工具以及功能会有不同。
以linux下为例,要使用外部查询,先设定外部查询所使用的工具,以及一些缺省选项:
:set grepprg=grep\ -nri\ –include=*.{php,js}
这表示vim的内部查询命令:grep将使用外部查询工具grep进行查询,注意这里两个grep表示不同的含义,前者表示vim的内部查询命令,后者是一个独立的文件查询程序。同时为grep程序指定了一些它自己的选项作为缺省值,-n表示在查询结果中显示该行所在文件中的行号,-r表示递归搜索指定目录下所有任意深度的子目录中的文件,-i表示忽略大小写,当然,忽略大小写会使查询速度慢很多。另外,使用–include(注意:include前有两个“-”,不知道为什么,wordpress将它们过滤成了一个)选项指定只搜索特定后缀名的文件。
:grep命令的格式为:
:gr[ep][!] {arguments}
和:vimgrep一样,!仍然用来表示不自动在当前窗口打开第一个查询结果。arguments因使用的外部查询工具而异,对于上面设定的grep,基本格式为:
:gr! function\ demo .
结合:set grepprg中的设定,它表示在当前目录下所有子目录中后缀为php和js的文件中查询function demo,且忽略大小写并不自动在当前窗口打开第一个查询结果。
无论是:vimgrep还是:grep,其查询结果都会显示在vim的quickfix列表窗口中,使用:copen和:cclose打开和关闭此窗口。另外还有一对对应的命令,:lvimgrep和:lgrep,它们与各自对应的命令不同的地方在于,其查询结果会显示在vim的location列表窗口中,location窗口是当前窗口的内嵌窗口,而不是像quickfix列表窗口那样是vim的全局窗口,平等于其它窗口显示在vim的上方或者下方。使用命令:lopen和:lclose打开和关闭location窗口。
:vimgrep和:grep有一些使用技巧:
前面说过用!防止vim自动在当前窗口中打开第一个查询结果,如果希望在新窗口中打开第一个查询结果,方法是:
:split|gr function\ demo .
即使用管道。
还有,在quickfix窗口打开的前提下,使用:colder和:cnewer可以前后查看此前做过的查询的结果,从而无须重新进行查询。
另外,对于:vimgrep,由于是模拟逐个打开文件再做查询从而导致速度变慢,使用:noautocmd命令在某些情况下可以对:vimgrep起到加速作用。
番外篇
某天,有个哥们儿很纳闷儿地问我究竟vim比eclipse好在哪里。
又某天,有个姐们儿很奇怪为什么公司其它人的编辑器都是白底儿(ultraedit或eclipse),而我的却是黑底儿的。
又又某天,又有个姐们儿在我:vimgrep的时候嫌速度不如她的ultraedit快,我一向不是个布道者,但却是个卫道者,速度嘛,看完:grep再说话!