igrep について

grep の復習

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

    % grep -n module *.tex    

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

    % grep -n "[0-9][0-9]-[0-9][0-9]-[0-9][0-9]" *.his    

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

    % man grep    
などして御自分でお調べ下さい。:-P

Mule の中から grep を使う

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

    % grep -n connection *.tex    

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

検索結果をもっと絞りこむことも出来るらしいですが、それはまたいつか...。

少くともここの計算機の grep は日本語ファイルの検索にも使えます。 私は普段はファイルは EUC で統一しているのですが、その場合は、 .emacs

(define-program-coding-system "*grep*" nil (cons *euc-japan* *euc-japan*)) 

とか書いておけばよろしいです。あるいはもっと大胆に、

(set-default-process-coding-system *euc-japan* *euc-japan*) 

とするのも手かもしれません。


igrep について

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

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

因みに、igrep を使えるようにするには、neumann 上なら .emacs

(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.elload-path 上に置いて、必要なら bytecompileしておけばよい です。

日本語の検索 (その1)

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

(define-program-coding-system "*igrep*" nil (cons *euc-japan* *euc-japan*))

と書いておくだけで OK.

ただし、最近の igrep.el のバージョン 2.83 というやつだと、shell-quote-argument を使って -0-9a-zA-Z_./ 以外の文字を全て\ でクォートしちゃいます。 当然、日本語は化け化けになっちゃうので、igrep.el 2.83 なら 479 行目にある (shell-quote-argument expression) は単に expression としてやらないとまずいです。 そんなわけで、私はいまだに 2.70 辺りを使っています。

日本語の検索 (その2)

ディレクトリによっては複数の文字コードのファイルが混在している場合もあります。 こんな時は JIS とか UNICODE にも対応し、できれば漢字コードを自動判別してくれるような grep が欲しくなります。

このことに関しては、最近になって、 成田さんが書かれた lv についている lgrep というものを知りました。 時間がないこともあって、まだちょっとしか使ってないのですが(ご免なさい)、とても素敵なもののように思います。 複数の漢字コードを使ってらっしゃる方は是非試してみて下さい。 lv 自体も素晴しいです。ただ、実行速度は

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

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

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

(setq igrep-program "lgrep")

を加えるだけです。そうすると gzip 等で圧縮されたファイルを指定すると zlgrep が無いと怒られますが、 これは例えば zlgrepzgrep にリンクしておいて、環境変数 GREP を lgrep に指定するか、それが嫌なら zgrep (これはシェルスクリプト) の先頭付近で egrep とかと並べて

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

みたいな行を加えておけば良いはずです。

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

置き換え方は lgrep の時と同様です。lgrep もこの jgrep も -e オプションがないので、.emacs に更に

(setq igrep-expression-option nil)

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

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

使い方の例

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 というのもあるみたいです。 また、後で説明するjam-zcat.elを入れておけば、そのまま C-c `C-c C-c で文書の該当箇所に飛ぶことも出来ます。 (Cf. jam-zcat) これは zgrep を呼び出しているのですが、Linux とか使ってる場合に /usr/doc/faq の下を見る時なんか重宝します。

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

dired との連継

Dired mode では、dired-do-igrep(-find) を使って、マークしたファイルやカーソルの下のファイルやディレクトリに grep をかけることができます。

補足

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

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

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


[Mule のページに戻る]