はじめに
Rustの練習として、ファイル検索・置換ツールamberを作ってみました。検索は昔ながらのgrep
から、最近だとack
やag
などいろいろありますが、置換に関してはいまだにfind ... | xargs sed -i '...'
くらいしかないように思います。
検索速度についても多少気にしていて、少なくとも固定文字列検索についてはgrep
/ag
あたりと遜色ないはずです。
リンク
使い方
インストール
ダウンロードしたzipを展開するとambs
/ambr
と2つファイルがあるのでパスの通ったところに置くだけです。
ambs
("amber search")が検索コマンド、ambr
("amber replace")が置換コマンドです。
検索
// カレントディレクトリから再帰的にkeywordを検索
$ ambs keyword
// pathから再帰的にkeywordを検索
$ ambs keyword path
デフォルトで以下のような設定になっています。
- 固定文字列検索
- カレントディレクトリから再帰検索
- VCSの管理ディレクトリ(
.git
や.hg
など)は無視 - バイナリファイルは無視
- (
.gitignore
の扱いはまだ実装途中です…)
オプション--regex
で正規表現検索も一応可能ですが、あまり動作確認もしていないので、正規表現を多用したい方にはおすすめしません。
固定文字列検索の場合、ファイルサイズの大きいものは分割してマルチスレッドで検索するので、数百MB~数GBのテキストを検索するような場合でもそれなりの速度が出ます。ここだけは他のツールより優位なところかもしれません。(需要があるかどうかは別問題ですが・・・)
文字列はUTF-8扱いなのでUTF-8な端末なら(当然検索対象もUTF-8限定ですが)日本語検索も可能です。検索結果については文字境界チェックをしているので、Shift-JISやEUC-JPの2バイト目が間違って引っかかったりはしないはずです。
(Shift-JISなども検索したい場合はpt
が良いと思います)
置換
// カレントディレクトリから再帰的にkeywordを検索してreplacementに置換
$ ambr keyword replacement
// pathから再帰的にkeywordを検索してreplacementに置換
$ ambr keyword replacement path
置換も検索とほぼ同様で、置換先の文字列を追加で与えるだけです。検索文字列が見つかる毎にデフォルトでは以下のようなプロンプトが出るので、置換する・しないを選択します。
(--no-interactive
を使うとプロンプトなしに全置換します)
Replace keyword? ( Yes[Y], No[N], All[A], Quit[Q] ):
また、検索文字列・置換文字列ともにファイルから読み込むことも可能です。
$ cat file1
keyword
$ cat file2
replacement
$ ambr --key-file file1 --rep-file file2
Unite.vim
Unite.vimで使う場合は以下のように設定してください。
if executable('ambs')
let g:unite_source_grep_command = 'ambs'
let g:unite_source_grep_default_opts = '--column --no-color'
let g:unite_source_grep_recursive_opt = ''
let g:unite_source_grep_encoding = 'utf-8'
endif
ベンチマーク
grep
,ag
,pt
,hw
,sift
との比較データは取ったのですが、長くなりそうなので別記事で。
(2016/3/4追記)
こちらに書きました。
まとめ
ファイル検索・置換ツールの紹介でした。本当は.gitignore
無視の実装が終わってから記事にしようかと思っていたのですが、意外と大変だったので作業途中ですが公開することにしました。
Issue/PRなどありましたらお気軽にどうぞ。