• 作成:

Shift_JISに対応しているのでag(the_silver_searcher)からrg(ripgrep)に乗り換えました

ggreer/the_silver_searcher: A code-searching tool similar to ack, but faster.

から

BurntSushi/ripgrep: ripgrep recursively searches directories for a regex pattern

に乗り換えました.

rgの方がagより速いことは知っていましたが, そこまでagの速度に不満を持っていなかったため, あまり乗り換える気にはなっていませんでした.

しかし, ついさっき, agとptとripgrep,どっちがどうでどれを使えばいいのか調べた予習 - Lambdaカクテルを読んで, rgはShift_JISのファイルに対応していると知って, 移行を決意しました.

まだまだShift_JISのファイルを見ることは多いのです.

しかし, 実際試してみたところ, -Eオプションの指定なしに日本語Shift_JIS文字列を探索することはしないようですね. それでもagが検索を諦めたShift_JISファイルのラテン文字部分は検索できましたが.

また, rg -E Shift_JIS ほげのように検索すると, 逆にUTF-8のファイルの検索は出来ないようです.

rgはagと違って正規表現のバックトラックなどを使えないようですが, ほとんど使ってないので問題にはならなそうです. 使いたい時だけgrepを使えば良さそうです. 圧縮ファイル検索も複数行検索もほとんど使っていません.

【Windows安心超音速grep】ファイルタイプ対応版rg検索によると Emacsインターフェイスはdajva/rg.el: Emacs search tool based on ripgrepより nlamirault/ripgrep.el: Emacs front-end for ripgrep, a command line search toolの方が良さそうですね. ファイルタイプとか一々入力しないで全文検索したいですし. と思いましたが, ripgrep.elはwgrepに非対応なので, 間違いなくrg.elの方が良いですね. helmを使わない検索はよくやる行為ではありませんし, RETを1回押すだけならそんなに手間でもないです.

helmインターフェイスはsyohex/emacs-helm-ag: The silver searcher with helm interfaceがrg対応しているので変数を設定するだけで良さそうです. microamp/helm-rg: Helm frontend for rg (ripgrep)とも比較検討してみましたが, プロジェクト内部検索とかやってくれる分helm-agの方がやはり良いですね.

というわけで全般的にagよりrgの方が良いから移行しよう! と移行作業を進めていたらバグっぽい挙動を発見しました.

バグの内容は, 文字列をシェルの変数に入れて, echoしたものを標準入力として与えると, 途中で探索を止めてしまうというものです.

私は

prg() {
    readonly local ps_result=$(ps aux)
    echo $ps_result|rg $@
}

のようにプロセスを検索するシェルスクリプトを組んでいて, これをagからrgに移行させていたので気がつくことが出来ました.

2018-05-03T19:18:02 ncaq@strawberry/pts/6(0) ~/Downloads
% ps aux > ps-aux.txt
2018-05-03T19:18:07 ncaq@strawberry/pts/6(0) ~/Downloads
% rg root ps-aux.txt|wc -l
347
2018-05-03T19:18:12 ncaq@strawberry/pts/6(0) ~/Downloads
% ps_result=$(cat ps-aux.txt)
2018-05-03T19:18:20 ncaq@strawberry/pts/6(0) ~/Downloads
% echo $ps_result|rg root|wc -l
203
2018-05-03T19:18:52 ncaq@strawberry/pts/6(0) ~/Downloads
% echo $ps_result|ag root|wc -l
347

のようにファイルとechoの標準入力では答えが違ってしまいます. 本来は最後まで検索するはずなのですが, echoした場合は途中で探索をやめてしまい, 結果も出てきませんし件数も異常になります.

issueを作りました. echo shell variable, ripgrep quit in the middle · Issue #908 · BurntSushi/ripgrep

というわけで, 移行するのは致命的なバグの修正を待ってからにすることにしました.

なんかこのバグzshとの相性の問題っぽいですね… bashだとrgもagも1しか出力しません.

2018-05-03T21:08:26 ncaq@strawberry/pts/9(0) ~/Downloads
% echo $ps_result|rg root|wc -l
203
2018-05-03T21:08:56 ncaq@strawberry/pts/9(0) ~/Downloads
% /bin/echo $ps_result|rg root|wc -l
347

/bin/echoを使ったら結果が変わるというおもしろ現象が発生しています.

会話の結果, これは私がzshのechoの使い方を間違えていたということがわかりました. zshのechoは\uをエスケープシーケンスと判断して変換します. それによってファイルが途中から解釈できなくなります.

簡単にはecho -Eを使えば回避できるでしょう.

bashとzshで互換性のある書き方はよくわからない…

実際に乗り換えてみると, 確かに速度が違いますね… 早く乗り換えれば良かったです.