grep的两个替代品(补充?)

GREP是我很常用的命令,尤其在浏览代码时,可以用它来搜索一个变量/函数在哪些文件里面被引用了。

但grep有一些不爽的地方,这两天看到了两个跟grep类似的东东,可以在一定场景弥补grep的不足,甚至是替代它。

ACK

http://betterthangrep.com/

ack的广告词是“better than grep, a source code search tool for programmers”,它旨在解决grep用在写代码时的诸多不爽:

1. 排除一些不需要搜索的文件/目录

在写代码时,我们常常会有.svn, .cvs这些目录,还有 foo~, #foo#这些临时文件/备份文件,以及一些二进制文件。要在grep命令行排除这些目录,是很麻烦的的,因为传统grep并没有这个能力,而是要结合find来使用:

grep pattern $(find . | grep -v .svn | grep -v .cvs | egrep -v '~$' | egrep -v '^#')

这不仅很繁琐,而且在文件很多时会因命令过长而出错。如果是在Windows系统上就相当让人抓狂了(是的,你可以用一个msys或者cygwin提供的bash来作为shell,以便它支持上述复杂的shell命令,但调用其它Windows程序的地方又悲剧了)。

而ack的解决办法很简单:把这些东西内置到程序里,搜索时自动忽略这些文件。

 

2. 让grep只搜索某些类型的文件,但要求搜索子目录

grep可以搜索子目录(用-R选项),但这种情况下你就不能再指定文件类型,所以传统的方法也是结合find来折腾:

grep pattern $(find . -name '*.pl' -or -name '*.pm' -or -name '*.pod' | grep -v .svn)

在GNU grep 2.5版本上,你可以用 --include=PATTERN --exclude=PATTERN 这两个选项来过滤文件类型:

grep -R pattern --include='*.pl' --include='*.pm' --include='*.pod' --exclude=.svn

这个命令行也挺长,而且你得有个GNU grep >= 2.5。

ack的解决思路是:1)缺省就搜索子目录;2)对常用编程语言,ack里面写好了对应哪些文件扩展名,比如perl是.pl, .pm和.pod,那么你只要指定按perl这个语言搜就行了。于是上述命令可以简化为:

ack --perl pattern

如果只想排除perl类型的文件,则可以用:

ack --noperl pattern

你可以--type-add TYPE=.ext[,ext2[,...]]或者--type-set TYPE=.ext[,ext2[,...]]来临时定制文件类型(如果要长期使用,可以修改~/.ackrc。

同时,也许你已经注意到了,其实ack也可以用来替代那一大堆find命令,用来搜索指定类型的文件本身(而不是文件内容),ack当然也支持,只需要添加-f 选项就行了:

ack -f --perl

 

ack的其它特点

  • 支持pcre
  • 缺省支持颜色,而且会比较智能地不使用颜色
  • 支持很多grep的选项,比如-A(--after-context), -B(--before-context), -C(--context), -H(--with-filename), -i(--ignore-case), -v(--invert-match), -w(--word-only)......

安装

Debian/Ubuntu上改名叫ack-grep了,用apt-get install ack-grep就可以装上了(命令名也是叫ack-grep而不是ack)。
ack是用perl5写的,并没有什么第三方依赖,所以在其它系统上安装也很简单,只要从CPAN安装App::Ack模块就可以了。另外该网站还提供了一个单文件版本(standalone version),只要下载后放到bin目录就行了(前提是安装了perl5)。
对于Windows,我用perl2exe做了个纯粹单文件版本: ack.exe

 

glark

http://www.incava.org/projects/glark

与ack关注点不一样的是,glark跟关注文件里面的内容,举两个例子说一下:

% glark --and=2 printStackTrace catch *.java

这表示在java代码中搜索printStackTrace和catch这两个词,要求这两个词出现的位置相差不超过2行;

 

% glark --or catch throw *.java

这表示要求搜出包含catch或者throw的行;

 

% glark --and=5 cout --or double float *.c

这表示要求某行包含double或者float,然后在其上下5行内有cout出现。

 

glark也支持pcre,也缺省支持高亮文件名和匹配文字,也缺省忽略非文本文件,还跟grep的命令行选项保持很高的兼容性。

glark是用ruby写的,也没什么第三方依赖。

glark也已经被Debian/Ubuntu收入(lenny开始就有了),用apt-get install glark即可安装.





posted @ 2012-01-03 11:58  巴蛮子  阅读(7354)  评论(1编辑  收藏  举报