grep を使っていると、 .git/
などを除外したいとか、ファイル名のパターンなどを指定したいとか、細かい要望が出てきて結局 俺々 grep ラッパースクリプトを作る羽目になる。
ずっと昔に自分で作ったスクリプトを長らく使ってきたけど、最近会社の同僚が ack (http://beyondgrep.com/) を使っているのを見て、そろそろ俺々スクリプトを卒業しようと思った。
ack を見てみたが Perl 製で、なんとなく入れるのがめんどい (注: 自分が CPAN 慣れしていない) し、起動が少し遅そう (注: 先入観)。
代わりに ag (The Silver Searcher, https://github.com/ggreer/the_silver_searcher) を使ってみることにした。
ag のウリは高速なことらしい。先ほどのページから抜粋すると、
- 固定文字列の検索に Boyer-Moore-Horspool strstr を使っている …… (知らないアルゴリズムだ)
mmap()
を使ってファイルを読み込む …… (これは GNU grep などもそうだったはず)- PCRE 8.21 以降なら JIT compiler を使う …… (PCRE にそんな機能が!)
pcre_study()
を呼ぶ …… (そんなのがあるのか)- ファイル名のマッチングも工夫してるらしい
- pthreads で並列化してるらしい
なるほど。でも実際に使ってみると、速さに大きく貢献しているのは「不要なファイルは検索対象にしない」という所の様子。
ag はデフォルトではテキストファイルしか検索対象にしない上、隠しファイル('.'
で始まるファイル) および、.gitignore
, .hgignore
, それから .agignore
(ag 独自のファイル) に書かれたものは検索しない。これにより、デフォルトで検索対象のファイルをかなり絞っているため、普段使いでかなり速い。もちろん、真面目にベンチマークしても速いと思うけど、デフォルトで速い設定になっているというのも有利な点だと思う。
.gitignore
の内容に従ってしまうのは、不便なこともあるのではないかと思ったけど、確かに .gitignore
に書かれたファイルは検索したいと思わないものが多く、自分のニーズに合っている気がした (参考: このあたり https://github.com/github/gitignore)。まぁだいたいバイナリですしね。
ag はオプションで検索対象ファイルを変えられるが、その説明がいまいちわかりにくかったのでまとめておく。
実はこの記事で書きたかった内容はこれがメイン。
オプション | テキストファイル | ignoreファイルに書かれたファイル | バイナリファイル | 隠しファイル |
---|---|---|---|---|
オプションなし | ○ | × | × | × |
-t | ○ | ○ | × | × |
-a | ○ | ○ | ○ | × |
-u | ○ | ○ | ○ | ○ |
- 他に
--hidden
,--search-binary
というオプションもあり個別に有効化できる。 - -u オプションを指定すれば全てのファイルを検索対象にできる。
ag は高速化にフォーカスしていて、ack のような機能の豊富さはない (ack は検索対象のプログラミング言語を指定できたりして便利そう)。けれども自分にとってはこれで十分という気がするし、ack が必要なら ack もインストールすればいいし。まぁしばらく使ってみようと思う。