[ホーム]-> [emacs]-> [活用法]-> [igrep]

igrep について

1. grep の復習

UNIX での全文検索には古来から grep が使われてきました。例えば端末で

    lucy~$ grep -n module *.tex

とやると、カレントディレクトリの拡張子が tex であるファイルで "module" という単語を含むものを見つけて、ファイル名と行番号、行の内容を書き出してくれます。 "module" の部分には、正規表現が使えます。例えば、

    lucy~$ grep -n "[0-9][0-9]-[0-9][0-9]-[0-9][0-9]" *.his    

とすると、拡張子 his のファイルから 96-08-01 みたいな文字列が含まれている所を検索出来ます。 この辺は皆さん、御存知のことと思うので省略します。詳しくは man grep などして御自分でお調べ下さい。

2. Emacs の中から grep を使う

Emacs には標準で grep を Emacs の中から呼び出すコマンドがついています。 例えば ~/tex というディレクトリにある拡張子 tex のファイルで、connection という単語を含むものを検索したい場合、 M-x  cd  RTN  ~/tex  RTN  M-x  grep  RTN とすると、ミニバッファで検索コマンドを聞いてくるので、

    lucy~$ grep -n connection *.tex    

と答えて RTN を押します。 (grep -n の部分は始めから挿入されてる。) すると、別の窓に結果が表示されます。 ここで C-x ` を押していくと、次々に見つかった場所にタグジャンプできます。 あるいは、検索結果の中から特定の場所に飛びたい場合は、その行にカーソルを移動して C-c C-c とすると、その場所に飛べます。

3. igrep について

そして igrep です。これは、grep のインターフェースを改造したもので、一番の売りはサブディレクトリにも対応したことです。 (実際は、find と xargs を内部から呼び出しています。 そういうわけで Windows95/NT で使う場合には、grep だけでなく、これらのコマンドもインストールしておく必要があります。 (GNU-Win32 であれば、release-17.1 以上が必要だそうです。)

なお、Emacs-20.x では初めから同等の機能を持つものがあるみたいです。

因みに、igrep を使えるようにするには、 .emacs.el

(autoload (function igrep) "igrep"
  "*Run `grep` PROGRAM to match EXPRESSION in FILES..." t)
(autoload (function igrep-find) "igrep"
  "*Run `grep` via `find`..." t)
(autoload (function dired-do-igrep) "igrep"
  "*Run `grep` on the marked (or next prefix ARG) files." t)
(autoload (function dired-do-igrep-find) "igrep"
  "*Run `grep` via `find` on the marked (or next prefix ARG) directories." t)

などと書いておきます。その他にも egrep や fgrep を使う設定を書いておいても良いです。 詳しくは igrep.el の先頭の方に書いてあるので、省略します。

他のマシンでは、更に igrep.el (2.93)load-path 上に置いて、必要なら bytecompileしておけばよいです。

4. 日本語の検索 (その1)

Linux の日本語化パッケージ (P)JE などにある t^2 さんがマルチバイト文字に対応して下さった GNU grep は、SJIS と EUC に対応しています。 私みたいに日本語の文章はほとんど EUC で書いている人や、Windows や DOS なんかの上で使っている人で SJIS で統一してる人などにはこれで十分でしょう。

ただし、少なくとも igrep.el のバージョン 2.83 以降では、shell-quote-argument を使って -0-9a-zA-Z_./ 以外の文字を全て \ でクォートしちゃいます。 Emacs 20 だと日本語が化け化けになってしまったりしたのですが、 Emacs 21 では取り敢えず大丈夫なようです。 (Emacs 20 では igrep.el 2.93 なら 510 行目にある (shell-quote-argument expression) は単に expression としてやらないとまずいです。)

5. 日本語の検索 (その2)

ディレクトリによっては複数の文字コードのファイルが混在している場合もあります。 こんな時は JIS とか UNICODE にも対応し、できれば漢字コードを自動判別してくれるような grep が欲しくなります。 こういう grep としては、成田さんが書かれた lv についている lgrep というものが良い感じです。 (ちなみに、私は less の代わりに lv を使っています。) 複数の漢字コードを使ってらっしゃる方は是非試してみて下さい。 ただ、実行速度は

   GNU grep+mb > jvim 附属の jgrep > lgrep

なので、この辺が気になる人や普段は EUC で十分な人などは日常的に使う方は通常の grep にしておくのがよいかも。 使い分けをする場合、例えば (setq igrep-program nil) としておけば、毎回どの grep を使うか聞いてきます。 自動的に exec-path 上の grep という文字列を含むプログラムファイルをテーブルにして持っているので、補完が効きます。 こうしておいても特に不便はないでしょう。

Emacs からは常に lgrep を使いたい方は、lv をコンパイル、インストールした後、 .emacs.el

(setq igrep-program "lgrep")
(setq igrep-expression-option nil)

を加えるだけです。 (下の行は、lgrep には -e というオプションがないため。) そうすると gzip 等で圧縮されたファイルを指定すると zlgrep が無いと怒られますが、これは、

  1. まず zlgrepzgrep にリンクします。

  2. そして、環境変数 GREPlgrep に指定するか、 それが嫌なら zgrep (これはシェルスクリプト) の先頭付近で egrep とかと並べて

          *lgrep) grep=${LGREP-lgrep}     ;;    
          

    みたいな行を加えます。

これで OK なはずです。

lgrep を知る前は、jvim2.0r についてきた文字コード自動判別機能つきの jgrep に行数を表示するパッチを当てたものを使ってました。 (行数に関するバグがあるそうです。北内さんが いくつかの不具合を修正したソースを書かれています。)

置き換え方は lgrep の時と同様です。 lgrep と同様 jgrep-e オプションがないので、.emacs.el には次のように記すことになります。

(setq igrep-program "jgrep")
(setq igrep-expression-option nil)

そうすると正規表現が - で始まる時とかは気をつけた方がいい気もしますが、 実はこれは igrep.elの方で勝手に \ でエスケープしてくれるようです。

同様にどの find を使うかは、igrep-find-program で指定できま すが、これは変更したい人は少ないでしょう。その他の option については igrep.el 内の User variables の箇所を見て下 さい。

ところで、lgrep はデフォルトでは出力を iso-2022-jp で出します。 (インストールの仕方にもよると思いますが。) この場合、出力バッファが文字化けしてしまうことがあるので、.lv-Oej という行を加えておくと、EUC Japan で出力してくれます。 ちなみに私は -c という行も加えています。 こうしないと私の環境では lv でスクロールしたときに反転してしまうので。

6. 多国語の検索

これは今の所 unicode を使うものしか成功していません。 iso-2022-jp-2 あたりのファイルでも latin-1 な文字を検索できると嬉しいのですが...。

が、逆に例えば utf-8 で書かれたファイルを igrep 経由で検索する場合なら、上の日本語の設定で大丈夫です。

7. 使い方の例

M-x igrep とするとミニバッファで検索語を聞い てくるので、例えば、

    grep  Expression: grep    

のように入力すると、次にファイルを聞いてきますので、

    grep  File(s): *.txt    

みたいに答えます。結果は *igrep* という名前のバッ ファに表示されます。ここで C-x ` とすると、検 索されたファイルを自動的に読み込み、該当行にジャンプします。更に C-x ` を繰り返せば、次々と検索された行に飛んでいきます。 また *igrep* バッファに移って目標とする行にカーソルを動かして C-c C-c とすると、その行に飛びます。 ディレクトリは何も指定しない場合は Emacs にとっての現在ディレクトリ、 即ち C-x C-f とした時にデフォルトで見る行が使われるようです。

ファイル検索の際に、*.gz のように拡張子 gz を指定した場合は、 zgrep を自動的に呼出してくれます。 M-x zgrep というのもあるみたいです。 そのまま C-c `C-c C-c で文書の該当箇所に飛ぶことも出来ます。 これは zgrep を呼び出しているのですが、Linux とか使ってる場合に /usr/doc/faq の下を見る時なんか重宝します。

再帰的にサブディレクトリを検索したい場合は M-x igrep-find を使います。 親元のディレクトリを指定するには File(s) のところで指定しても良いですし、 M-x cd でディレクトリを移るのもありでしょう。

8. dired との連継

Dired mode では、dired-do-igrep(-find) を使って、マークしたファイルやカーソルの下のファイルやディレクトリに grep をかけることができます。 このコマンドを特定のキーに割り当てる方法については、 dired のキー割り当ての項 に書かれているようにフックを使います。

9. 補足

C-x ` でファイルを開いていくと沢山ファイルを開いてしまって 面倒だという人もいますが、 そういう場合は C-x C-b でバッファメニューを開いてまとめて消せば 問題ないでしょう。私は .emacs.el

(global-set-key "\C-x\C-b" 'buffer-menu)

として、C-x C-b でバッファメニューを開いたときに カーソルもそこへ飛ばすようにしています。


[ホーム]-> [emacs]-> [活用法]-> [igrep]