grep の高速便利な代替 ag

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 もインストールすればいいし。まぁしばらく使ってみようと思う。

 


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です