Edited at

Rustでファイル検索・置換ツールを作ってみた

More than 3 years have passed since last update.


はじめに

Rustの練習として、ファイル検索・置換ツールamberを作ってみました。検索は昔ながらのgrepから、最近だとackagなどいろいろありますが、置換に関してはいまだに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などありましたらお気軽にどうぞ。