2013年11月23日土曜日

zip とか tar の中身を grep するツール

zipやtar などのアーカイブの中身を、いちいち展開することなくそのまま検索でき、 かつ、ShiftJis とか EUC など日本語コードの違いも、よしなに扱う grepライクな python スクリプトを作ってみた。
(ググって探せば、先人の作ったもっといいものが見つかるような気もするけど)

jzgrep.py

スクリプトのソースは ここ
動かすには、python2.6 以上が必要。でも、python3 では動かない。
動作確認は、linux と os-x10.6 でしか行なっていない。

使い方は、$ python jzgrep.py --help | less を参照。
$ python jzgrep.py --help
Usage: jzgrep.py [OPTIONS] PATTERN [FILE ...]
  PATTERN  -- 正規表現パターン (Python の `re' モジュールを使っています)
  FILE...  -- PATTERN で検索するファイル。省略時は stdin。
  OPTIONS
       --help -- このメッセージを表示して終了する
       -n     -- 行番号を表示
       -l     -- PATTERN に一致する行を含むファイル名だけを出力
       -H     -- 出力する行の先頭にファイル名を付ける。
                 (検索するファイルが複数の場合は、これがデフォルト)
       -h     -- 出力する行の先頭にファイル名を付けない
                 (検索するファイルが一つの場合は、これがデフォルト)
       -i     -- 大文字小文字を区別しない (re.IGNORECASE)
       -s     -- 警告メッセージを出さない (e.g [Warning]: Cannot decode ...)

対応しているファイル・タイプは、
  • 普通のテキストファイル
  • gzip, bzip2
  • 暗号化していない zip 類 (たぶん epub とか jar も)
  • tar とその圧縮ファイル( tar、 tar.gz 及び tar.bz2)
また、tar や zip の中の tar や zip 、さらにその中の tar や zip、 さらに… も再帰的に検索できる筈。

日本語エンコーディングは、今のところ
utf-8, cp932, euc-jp, iso2022_jp
の4種類だけに対応している。
(他の文字コードについては、ソース中の _encodings 変数や matchtext 関数を、 少しだけ書き換えれば対応できるかもしれない)

但し、jzgrep.py はとても遅い!
たぶん、異なる日本語コードの照合処理について、こんな感じで、
for enc in ("iso2022_jp", "utf-8", "euc-jp", "cp932")
  try:
    m = re.search(PATTERN, TEXTLINE.decode(enc))
    if m: return m
  except UnicodeError: pass
return None
総当りでチェックしているからだと思う。
それに、ほんのたまにだけど、 間違って余計なものにヒットしちゃうこともある。かな?

0 件のコメント:

コメントを投稿