改変スクリプト

vimのgrepの設定と使い方


vimやgvimでgrepを使用する方法は内部grep(vimgrep)と外部grepの2種類あります。

   長所  短所
 内部grep
 (vimgrep)  
 ・日本語や日本語pathも問題なく扱える。
 ・WindowsのUNCパスも使用できる。
 ・ファイルごとに文字エンコーディングが違っていても問題ない。
 ・vim/gvimで読込可能なら全て検索可能。

 ・速度が外部grepに比べて非常に遅い。
 ・最後の編集位置などの履歴が消えてしまうことがある。
 これらは検索対象ファイル数が多くなるほど問題になる。

 外部grep
(GNU/cygwin grep、findstr等)
 速度がvimgrepに比べて圧倒的に速い。
 
 ・日本語や日本語pathの扱いに問題がある場合がある。
 ・ファイルごとに文字エンコーディングが違う時、特定の文字エンコーディングしか検索できない。
 ・utf-8のBOM付きの場合、最初の一文字が検索できない事がある。


内部grep(vimgrep)は vimに普通のファイルとしてバッファに読み込んでから grep同等の処理を行っているため、速度の問題は対処しようがありません。
grepの結果ヒットしたファイルが2000ファイルあれば2000ファイルを読み込んだのと同じ処理が行われますので、それだけのバッファを確保します。
大抵は問題有りませんが、大量のファイルを vimgrepしてヒットすると一部の動作やバッファ管理系などのプラグインが重くなる事もあります。

外部grep(GNU grep、cygwin grep等)は、速度は圧倒的に速いのですが、日本語(全角文字)の扱いに若干問題が出てくる事があります。
たとえばcp932のファイルの「だめ文字」や、vimの内部エンコーディングと異なる文字エンコーディングの日本語ファイルを扱いたい場合などは、「QFixGrep」やnkfなどの日本語grepヘルパーが必要になります。
英数字しか使用しないなら全く問題はありません。
またBOM付きutf-8ファイルでは最初の一文字が外部grepで検索できないことがあります。
これはBOMが文字ではないバイト列としてファイルの先頭に埋め込まれているためで、正規表現で行頭を検索する場合などに問題となります。
特にWindowsの場合はメモ帳でutf-8のファイルを開いて保存すると強制的にBOM付きへ変換されてしまうので気をつける必要があります。

単純に英数字の場合は外部grep(:grep)を使用して、日本語の場合は内部grep(:vimgrep)を使用すると問題が起きにくいでしょう。
他のエディタでは異なる文字コードのファイルが混在していると grepできなかったりする事も多いのでvimgrepはアドバンテージになるかもしれません。

以下には、双方の設定と簡単な使い方、外部grepでの日本語の文字化け、Windowsの vim/gvimをUTF-8化した時などの外部grepの問題と対処法について書かれています。


内部grep(vimgrep)の使い方

vim 7.0以降ならコマンドモードから vimgrep が使えます。
以下のように実行すると、"検索文字"をカレントディレクトリのtxtファイルから検索して、最初にマッチした行に移動します。
:vimgrep 検索文字 *.txt
最初にマッチした場所へ移動したくない場合は / で検索ワードを囲んで j オプションを指定します。
:vimgrep /検索文字/j *.txt
いずれにしても / 自身を検索したい場合は、/ をエスケープしてやる必要があります。
再帰検索を行いたい場合は、ファイル名を **/*.txt のように **/ 付で指定します。
:vimgrep 検索文字 **/*.txt
検索した後は :copen でQuickfixウィンドウを開いて、検索結果を一覧表示、選択が可能です。
Quickfixウィンドウを開かなくても :cp(cprev)、:cn(cnext) で前後の結果へジャンプできます。

検索後に自動でQuickfixウィンドウを開くには次のように実行します。
cw は cwinの略表記です。
:vimgrep 検索文字 *.txt |cw
また、次のように設定すれば、コマンドから grep と打ってもvimgrepが使用されます。
set grepprg=internal

外部grepの使い方

grepをコマンドプロンプト(shell)から使えるようにして、次のように.vimrcに設定すれば使用できるようになります。
(基本的にはデフォルトのままでも使用可能です)
set grepprg=grep\ -nH
unix系の場合はgrepがほぼ標準で入っているので、これで設定は終了です。
Windows2000/Xp/Vistaの場合デフォルトでは findstrが設定されますが、findstrはcp932専用で正規表現も貧弱ですので出来れば外部grepを使用する事をおすすめします。
英数字のみの検索かcp932のファイルしか扱わないなら findstrでも問題はありません。

Windows用grepの入手場所と設定

Windows用のgrepをまだ入手していない場合、以下の場所からgrepを入手することが出来ます。
GNU grepについては UTF-8で検索できないマルチバイト文字(日本語)があるようなので推奨しませんが、英数字のみの検索かcp932のファイルしか扱わないなら問題はありません。

 findstr  Windows(2000以降)標準コマンド
 cygwin  http://www.cygwin.com
 yagrep  http://www.kt.rim.or.jp/~kbk/yagrep/
 jvgrep https://github.com/mattn/jvgrep
 GNU grep
 http://gnuwin32.sourceforge.net/packages/grep.htm

個人的には cygwinのgrepを使用しています。


findstr

Windows(2000以降)のデフォルトとして以下のように設定されます。
set grepprg=findstr\ /n
findstrのオプションや正規表現についてはWindowsのヘルプでfindstrを検索して下さい。
findstrはcp932専用ですので、英数字以外はUTF-8などで検索できない事が多々あります。


cygwin

コマンドプロンプトから使用したい場合は cygwinをインストールしてから、インストールしたディレクトリのbinにpathを通してやります。
cygwinのbinにpathが通っている場合は _vimrcに以下のように設定します。
set grepprg=grep\ -nH

cygwingrep.zip に必要なファイルを抽出してあるので、vimと同じディレクトリか、適当な場所に解凍して使用する事も出来ます。
  1. cygwingrep.zip を適当な場所に解凍します。
    解凍して出来た binの中に grepに必要なファイルが全て含まれています。
  2. c:/cygwinに解凍したとしたら _vimrcへ以下の設定を 追加します。
    "C:\cygwin\binにgrepがある場合
    set grepprg=c:/cygwin/bin/grep\ -nH

cygwin 1.7 の場合は$CYGWINも設定してやるとよいかもしれません。
set grepprg=c:/cygwin1.7/bin/grep\ -nH
let $CYGWIN = 'nodosfilewarning'
cygwin 1.7のgrepはUTF-8がデフォルトなのでVimから直接扱う場合には日本語ファイル名が扱えません。
日本語を扱いたい場合は「QFixGrep」等なんらかのgrepヘルパーを使用する必要があります。


yagrep

yagrep を使用する場合もダウンロードして、vim/gvimの実行ファイルと同じフォルダにコピーすれば使用できるようになります。
実行ファイル一つで動作するので手軽ですが、独自オプションはバグや問題が起きることがあるので設定しないで使用するほうが良いようです。
set grepprg=yagrep\ -nH

yagrepは日本語対応という事になっていますが、最新版(2009/03/31)ではダメ文字は検索できません。
またutf-8でマルチバイトオプションを設定すると検索できなくなる文字などもあります。
上記バージョンではマルチバイトオプションは使用しないで下さい。
各種オプションについても、独自オプションはバグが多いので出来るだけ使用しない方が問題が起きにくいようです。
これらの問題は yagrepの作者に認識されていますが修正の予定は無いようです。


jvgrep

jvgrepは異なるエンコーディングのファイルが混在していても日本語でgrepを行う事が可能です。
https://github.com/mattn/jvgrep

jvgrepにpathが通っているか Vimと同じディレクトリにあるなら以下のように設定します。
set grepprg=jvgrep
pathを通していないなら pathは環境に合わせてフルパスで指定して下さい。

(注意)
現在の jvgrep(ver. 0.7)は開発中で以下のような制限があります。
  • 正規表現使用時に ignorecase(大文字小文字同一視)は使用できません
  • 限定的な正規表現しか使用できません
    (具体的な事は jvgrepのドキュメントを参照して下さい)
  • utf-8に対応していますがBOMには対応していません
  • オプションが一般的なgrepと異なるので気をつける必要があります
  • エンコーディング処理の関係で一般的なgrepより速度的に遅くなります
  • Windowsで内部エンコーディングをutf-8に設定している場合は使えません。


GNU grep

GNU grepについてはUTF-8のマルチバイト文字(日本語)で検索できないものがあるようです。
英数字のみか、cp932のファイ ルしか扱わないなら問題はありません。
Binariesと Dependanciesの zipファイルを同じディレクトリに解凍します。
実行に必要なのは bin だけです。
コマンドプロンプトから使用したい場合は pathを通して下さい。

単にgrepだけを使用する上では FindUtilsは必要有りませんが、grep.vimなど一部のプラグインで使用するものもあるので入れておいた方がよいでしょう。
古いバージョンではマルチバイト文字(日本語)の扱いが異なる事があります。

binにpathを通した場合は _vimrcに以下のように設定します。
set grepprg=grep\ -nH
pathを通していない場合はフルパスで指定します。
"C:\Gnu32\binにgrepがある場合
set grepprg=c:/Gnu32/bin/grep\ -nH


外部grepの使い方

設定が済んだら、以下のように実行すると、"検索文字"をカレントディレクトリのtxtファイルから検索します。
:grep 検索文字 *.txt
検索した後は :copen でQuickfixウィンドウを開いて、検索結果を一覧表示、選択が可能です。
Quickfixウィンドウを開かなくても :cp(cprev)、:cn(cnext) で前後の結果へジャンプできます。
オプションについては、使用する各grepのマニュアルを参照して下さい。
再帰検索のオプションは大抵 -r (findstrは/s)です。
:grep -r 検索文字 *.txt
検索後に自動でQuickfixウィンドウを開くには次のように実行します。
cw は cwinの略表記です。
:grep 検索文字 *.txt |cw

ASCII文字(英数字)か内部エンコーディングと同じファイルしか grep しないならほとんど問題はありませんが、そうでないなら 外部grepの問題点 を参照してください。


外部grepの問題点

基本的に内部エンコーディングと同じファイルを扱っている限り、日本語はfgrep(固定文字列検索)で行うようにしていればほとんど問題なく扱えます。

内部エンコーディングと異なるファイルを日本語検索する場合は nkfや「QFixGrep」などでエンコーディング変換する必要があります。
またWindows版vim/gvimの内部エンコーディングをutf-8化している場合は日本語ファイル名(path)にも気をつける必要があります。

ダメ文字」については正規表現で検索は出来ませんが fgrep(固定文字列検索) を使用すると検索可能です。
日本語でgrepが必要になるケースは少ないと思うので、日本語の場合は通常fgrepを使用する方が良いかと思います。

Windows / Linux 共通の問題

  • utf-8のBOM付きの場合、最初の一文字が検索できない事がある。
    BOMは文字ではないバイト列としてファイルの先頭に埋め込まれているため、正規表現で行頭を検索する場合などは検索不可。
  • ucs2-leなどリトルエンディアンのファイルは検索できない。

Windowsの場合

Windowsでvim/gvimの内部エンコーディングを変更して、外部grepを使用した場合の問題点を表にまとめました。
Windowsでのデフォルト内部エンコーディングはcp932(Shift_JIS)です。

 内部エンコーディング
 日本語ファイル名  cp932のファイル  utf-8のファイル  eucのファイル
 cp932
 日本語も表示される
 ダメ文字以外の日本語検索は可  日本語検索不可  日本語検索不可
 utf-8  日本語部分の文字化け/指定不可  日本語検索不可
 日本語検索可
 日本語検索不可
  • 「日本語ファイル名」にはpathも含みます。
    指定不可はコマンドモードから日本語ファイル名(path)が指定できないだけなので、カレントディレクトリ以下のファイルしか検索しないなら問題はありません。
  • 日本語検索不可の場合、ASCII文字で検索することは可能ですが、日本語部分のgrep表示は文字化けしています。
  • Windowsのメモ帳でutf-8のファイルを保存すると、BOM付きに強制変換するので、最初の一文字が検索出来なくなる事があります。
具体的なダメ文字については「Shift_JIS(cp932)の「ダメ文字」」を参照して下さい。

Linux(Ubuntu)の場合

 内部エンコーディング
 日本語ファイル名  cp932のファイル  utf-8のファイル  eucのファイル
 utf-8  日本語も表示される  日本語検索不可
 日本語検索可
 日本語検索不可

shellと内部エンコーディングが基本的に一致しているので、問題はutf-8以外のファイルの日本語検索不可だけになります。

結論

速度的に問題ないならvimgrepを使用します。
速度が問題の場合や、検索対象ファイル数が多くて重くなったり、最後の編集位置などを消されたくない場合は外部grepを使用します。

速度的な問題から外部grepを使用する場合で、うまく外部grepで扱えない事があるのは以下のような場合です。
以下のような場合は「QFixGrep」やnkfなど、何らかの日本語grepヘルパーなどが必要になります。

Windows(vimの内部エンコーディング cp932)の場合

  • cp932のファイルで「ダメ文字」を扱いたい場合
  • cp932以外のファイルを外部grepで日本語検索したい場合

Windows(vimの内部エンコーディング utf-8)の場合

  • 日本語を含むファイル名やpathが含まれている場合
  • utf-8以外のファイルを外部grepで日本語検索したい場合

Linux(Ubuntuでvimの内部エンコーディング utf-8)の場合

  • utf-8以外のファイルを外部grepで扱いたい場合
    nkfを使用して変換する方法もある


 
Comments