Lambdaカクテル

ソフトウェア開発者です.玉石混淆です.

agとptとripgrep,どっちがどうでどれを使えばいいのか調べた予習

イマドキの高速検索系ツールといったらagっしょ,みたいな気持ちでいたら最近はptというのがあるらしいですね.流行についていけないのでもうおじさんです. 他にもこの手のツールとしてripgrepなどがあります.流行り廃りの激しいツールのジャンルってありますよね.タスクランナーとか.

tl;dr

  1. 混在したエンコーディングを横断して検索したい?⇒ripgrepを使おう
  2. 圧縮したファイルの中も検索したい?⇒agを使おう
  3. バックレファレンスと先/後読みを使いたい?⇒agを使おう
  4. 独自のファイル形式を定義したい?⇒ripgrepを使おう
  5. 速いほうがいい?⇒ripgrepを使おう
  6. ポータブルなシングルバイナリが欲しい?⇒ptを使おう

agの復習

そもそもagが生まれた?背景はどういったものだったのでしょうか.ag以前にあった全文検索系ツールを調べてみます.

ag(1) – The Silver Searcher. Like ack, but faster.

Recursively search for PATTERN in PATH. Like grep or ack, but faster.

https://github.com/ggreer/the_silver_searcher/blob/master/doc/ag.1.md

agはackやgrepの代替となることをdocumentで宣言しています.速さの他に,ackやgrepと比べてどのようなメリットがあるのでしょう.

It started off as a clone of Ack, but their feature sets have since diverged slightly.

https://geoff.greer.fm/ag/

Ackのクローンとして始まって,より沢山の機能が積まれるようになったようです.

https://shoyan.github.io/blog/2015/10/28/highway-faster-than-ag/ では,agが開発された背景について触れられています.要約すると,

  • grep.gitignoreなどを解釈しないため,使い勝手が悪い.
  • ackは.gitignoreなどを解釈し,デフォルトでディレクトリを再帰的に検索でき,ファイルタイプを指定可能で,検索結果をファイル単位でまとめて表示できる.
  • ackはperl製で速度に限界がある.
  • agは高速なackを目指して開発された.

agはCで書かれているので,速度の面では圧倒的に優位ですね. さて,agにも欠点があり,EUC-JPやSJIS対応が不十分であったり,検索結果の出力順序が変わったりします.

grep ack ag
速度 基準 比較的遅い? 比較的速い
言語 C perl C
ディレクトリを再帰的に検索 -rオプションが必要 デフォルトでする デフォルトでする
ファイル種類を指定 できない できる できる
ファイル種類を除外 できない できる できる(名前ベース)
独自のファイル種類を定義 N/A できる できない
UTF-8/EUC-JP/SJISが混在した検索 できない(1つのエンコーディングのみ) できない(1つのエンコーディングのみ) できない(1つのエンコーディングのみ)
圧縮ファイル内の検索 できない できない gz/xzで可

ripgrep

ポストagとして有名なのはripgrepでしょうか.ripgrepは以下の特長をアピールしています.

  • agよりも完成度の高い,.gitignoreの完全サポート.
  • カスタムファイルタイプの定義による絞り込みと除外.
  • UTF-8でないエンコーディングのサポート.

ただし,ripgrepには以下のような欠点があります.

  • 有限オートマトン正規表現エンジンを使っているため,バックレファレンスや先/後読みが使えない.
  • 今のところ,圧縮ファイル内を検索できない.
  • 複数行検索をサポートする予定はない.

ちなみにripgrepはrust製です.初めてrustプロダクトを見ました.

pt

一番気になっていたptについてはどうでしょう.agに対抗した感じのネーミングに好感度が上がります.

ptは以下の特長をアピールしています.

ちなみにptはgo製です.goなのでシングルバイナリが生成できますね.

ripgrepが主張する特長をカバーできているか確認してみます.

  • .gitignoreに対応している(“完全"サポートかどうかは不明).
  • カスタムファイルタイプを定義できなそう.
  • UTF-8以外のエンコーディングをサポートしている.

ripgrepの欠点をカバーするかどうかについてはどうでしょう.動かして確認しました.

  • バックリファレンス,先/後読みは動作しない.(goの正規表現エンジンもたしか有限オートマトンでしたね.)
  • 圧縮ファイル内を検索できない.
  • 複数行検索ができない.

まとめ

いくつか欲しい機能もあわせて比較しました.

grep ack ag ripgrep(rg) pt
速度 基準 比較的遅い? 比較的速い 速い ag並み
言語 C perl C Rust Go
ディレクトリを再帰的に検索 -rオプションが必要 デフォルトでする デフォルトでする デフォルトでする デフォルトでする
ファイル種類を指定 できない できる(shebangも読める) できる できる できる
ファイル種類を除外 できない できる できる できる できる
独自のファイル種類を定義 N/A できる できない できる できない
UTF-8/EUC-JP/SJISが混在した検索 できない(1つのエンコーディングのみ) できない(1つのエンコーディングのみ) できない(1つのエンコーディングのみ) できる できる
圧縮ファイル内の検索 できない できない gz/xzで可 できない できない
出力桁数の制限 できない できない -W/--widthオプション -M/max-columnsオプション できない
バックリファレンス できる できる できる できない できない
先/後読み -Pオプションで可 できる できる できない できない
マッチした前後行の表示 -A/-B/-Cオプションで可 grepと同様 grepと同様 grepと同様 grepと同様
順序が 変わらない 変わらない 変わる 変わる(-j1でシングルスレッドにすれば可) 変わる