動機
ログを絞り込むとき、こういう書き方になりがちです。
cat app.log | grep ERROR | grep timeout | grep -v healthcheck | grep -v retry
条件が増えるたびに | grep が伸びていき、特に除外条件を複数つけたいときに煩雑になります。
正規表現もほとんどの場面では不要で、単純に「この文字列を含む」「この文字列を含まない」を並べられれば十分なケースが多いので、それだけに特化したフィルタコマンドを作りました。
pipgre
pipe + grep で pipgre。
先ほどの例がこう書けます。
cat app.log | pipgre ERROR timeout -V healthcheck retry
引数に書いた文字列はAND条件のinclude、-V 以降に書いたものはexclude。シンプルにそれだけです。
インストール
Rustのビルド環境があれば以下でインストールできます。
$ git clone https://github.com/rytkmt/pipgre.git
$ cd pipgre
$ cargo build --release
$ cp target/release/pipgre ~/.local/bin/ # PATHの通ったところへ
使い方
基本はパイプで渡してフィルタするだけです。
"ERROR" を含む行
cat file.txt | pipgre ERROR
"ERROR" AND "timeout" を含む行
cat file.txt | pipgre ERROR timeout
"ERROR" を含むが "healthcheck" を含まない行
cat file.txt | pipgre ERROR -v healthcheck
除外系のオプション
| オプション | 挙動 |
|---|---|
-v <word> |
直後の1語をexclude |
-V |
以降すべてexclude |
-G |
-Vを解除してincludeに戻す |
-v はgrepと同じ感覚で使えるようにしました。条件が多い場合は -V でまとめてexcludeに切り替えるほうが楽です。
-v を個別に指定
cat app.log | pipgre ERROR -v healthcheck -v retry -v cron
-V でまとめて
cat app.log | pipgre ERROR -V healthcheck retry cron
使いどころ
自分が実際に使っている場面をいくつか紹介します。
プロセス探し(bundleとspringは除外したい)
ps aux | pipgre ruby -V bundle spring
アクセスログから特定ユーザーのエラーだけ
tail -f access.log | pipgre user_id=123 -v 200 -v 301
gitログからfixコミットを探す(mergeやtypoは除外)
git log --oneline | pipgre fix -V merge typo
specファイル探し
find . -name "*.rb" | pipgre spec model -v factory
grepとの違い
- 正規表現なし。文字列マッチのみなのでエスケープ不要
- 複数条件をワンコマンドで書ける
- パイプ専用(ファイル引数は取らない)
grepの代替というよりは、パイプラインで手軽に絞り込みたいときの補助ツールという位置づけです。
正規表現が必要なケースは素直にgrepを使えばよいと思います。
まとめ
地味なツールですが、ログを眺めるときやプロセスを探すときに毎回使っており、個人的にはかなり重宝しています。
同じ不便さを感じている方がいれば、ぜひ試してみてください。