先日コード修正のために検索コマンドを幾つか使ったので簡単なまとめを投稿します。
問題になったコード
@adults = User.select(:id).where("age >= ?", 20).map(&:id)
pluckを使った方が良いですね
@adults = User.where("age >= ?", 20).pluck(:id)
複数のファイルで同じような記述をしている可能性があるので ".map(&:id)" が含まれるファイルを検索します。
基本のfindコマンドで検索
find . -name *.rb |xargs grep '.map(&:id)'
大抵の環境で動作するので覚えておくといいかもしれないですね。
検索範囲が広い場合は速度が気になるかもしれません。
ackコマンドで検索
普段はackを使っています
Macを使っていれば Homebrewで簡単にインストールできるのでオススメです
使い方も簡単
ack '.map\(&:id\)'
ackとほぼ同じように使えてより高速な https://github.com/ggreer/the_silver_searcher というものもあるようです。
こちらもHomebrew でインストールできるので、これから使いはじめるのであればこちらのほうが良いのかもしれないですね。
コマンドはこんな感じらしいです
ag [options] PATTERN [PATH]
ackと同じように使えそうですね。
mdfindコマンドで検索
ソースコードの検索ではあまり使わないですが、Macにはmdfind というコマンドが有ります。
mdfind "kMDItemTextContent == '.map(&:id)'" -onlyin ./
Macの中に保存してある全てのファイルから探したいという場合はこのコマンドを使うといいと思います。
spotlightをコマンドラインで実行するためのコマンドというイメージです。
オプションでかなり詳細に絞り込むことが可能なので、使いこなせればいろいろできそうですね。
File Metadata Query Expression Syntax
たまにCPUを独占してファンを唸らせているmdworker が作成したindexを利用するのでfindに比べるとかなり高速です。
git-grepコマンドで検索
社内で他に良い検索方法が無いか聞いてみたところ、ソースコードを検索するならgit-grep が一番良いと教えてもらったので、
最後にgit-grep を簡単に紹介します。
使い方
git grep '.map(&:id)'
gitでバージョン管理をしていることが前提になりますが、かなり高速で良いですね。
個人的に気に入ったのは検索条件の設定が簡単だという点です。
例えば、取得した結果を return で返却している箇所を探したいという場合は以下のようにすればOKです。
git grep -e '.map(&:id)' --and -e return
--andの他に --or, --not が使えます
正規表現を使うよりも簡単です。
速度比較
それぞれのコマンドで実際に速度に差があるのかを計測してみました。
計測対象には rails4 を選びました。
計測対象: rails4
検索文字列: FIXME
※ それぞれのコマンドで3回計測しています
ack
$ ack -l FIXME 0.54 real 0.44 user 0.09 sys 0.55 real 0.45 user 0.09 sys 0.53 real 0.44 user 0.08 sys
git grep
$ git grep FIXME 0.06 real 0.03 user 0.06 sys 0.06 real 0.03 user 0.06 sys 0.06 real 0.03 user 0.06 sys
mdfind
$ mdfind "kMDItemTextContent == 'FIXME'" -onlyin ./ 0.04 real 0.00 user 0.00 sys 0.01 real 0.00 user 0.00 sys 0.01 real 0.00 user 0.00 sys
git grep が一番早いと予想していましたが、mdfindの方が早いという結果が出ました。
ただ、mdfindはソースコードの検索としては少し使いにくいですね。
ack は普段使っていて遅いと感じることは少ないのですが、こうして比較してみるとハッキリとした差がありますね。
個人的にはack がオススメですが、普段git を使って開発をしているのであれば、
git grep の方が使いやすいかもしれませんね。