トップ 差分 一覧 ソース 検索 ヘルプ PDF RSS ログイン

grep風テキスト処理ツール.py

[Python]

gred.py

gred.py.txt(663)

概要

grepとsedのあいのこのようなスクリプト。
オプション指定はgrep風。
正規表現指定構文はsed風だが、マッチ動作はgrep風。

思い出:Windowsのコマンドプロンプトでgrepが使いたくて作ったツール。ログ解析ソフトのサポートをしてたときにはかなり活躍した。
今はPowerShellでそれなりに高度な正規表現マッチができるので、いい時代になった。

動作要件

Python 3以上。

  • ファイルのエンコードは、デフォルトではシステムのコンソールのエンコード(sys.stdout.encoding)と同じとみなされる。UNIX系のシステムであれば、環境変数LANGに依存する。WindowsではShift-JISとみなされる。エンコードが違うと、ほとんどの場合でファイルオープンの際にエラーになる(Pythonは自分がデコードできない文字に遭遇すると例外を発生させる)。
  • ファイルパスの末尾にコロン(:)で区切って、ファイルのエンコードを明示的に指定することが可能。出力は sys.stdout.encoding になる。
> gred.py /regex/ target_file.txt:utf-8
  • gredは引数として与えられた正規表現パターンをsys.stdin.encodingでデコードするので、上記文字コードの制約をクリアしていれば、日本語のマッチも問題なく行える。

オプション

i: 正規表現で大文字小文字を区別しない。
n: 結果に元のファイルの行番号を表示する。cオプションとは排他。
c: マッチした行をカウントして、その合計結果だけを表示。s///とは一緒に使えない。また、nオプションとは排他。
v: 指定した正規表現にマッチしない行を表示する。s///とは一緒に使えない。
H: 表示結果の先頭にファイル名を表示。

grepのように使う

上記すべてのオプションが使用可能(cとnは排他)。
マッチさせたいパターンは、必ず//で囲う必要がある(/正規表現/)。grepのように単純に"pattern"として文字列を指定できない(この辺がsed風)ので注意。

2008年6月26日の10時台のログのみ表示:

python gred.py "/time=\"?2008-06-26 10:/" example.log
  • WindowsでCPythonをインストールした場合、拡張子".py"との関連付けが行われるので、スクリプトの実行時にPythonを明示的に呼び出す必要はない。以下、実行例は明示的にPythonを呼び出さない方法で記載する。
gred.py "/time=\"?2008-06-26 10:/" example.log
  • Windowsのコマンドプロンプトの場合、正規表現は""で囲わないと、メタ文字の一部が正しくスクリプトに渡らないので、注意(UNIXシェルの''と同じ)。
  • また、ダブルクォーテーション(")文字を正規表現に含めたい場合は、この例のように\でエスケープする必要がある。

ログ中にattackという文字列がある行の行数をカウント(cオプション):

gred.py ic "/attack/" *.log
  • iオプションは、正規表現マッチで大文字小文字を区別しない。
  • ファイル指定にワイルドカードを使用することができる(正確にはDOSのワイルドカードではなく、Pythonの標準モジュールglobを使って、UNIXシェルのグロブ展開を行う)。
  • 各ファイルに/attack/にマッチする行が何行あるか、数字だけが表示される。ファイル名も表示したい場合には、以下のようにHオプションも指定する。
gred.py icH "/attack/" *.log

attackという文字列が含まれていない行だけをカウント(vオプション):

gred.py icvH "/attack/" *.log

連続したパターンを指定する(後方参照の使用):

gred.py "/(\d{1,2})\-\1/" example.log
  • 2桁までの同じ数字がハイフンで区切られているパターン(9-9、33-33など)にマッチする。

正規表現内での後方参照は、\numberが使える(Pythonの正規表現の仕様どおり)。

フィルタ結果に元のファイルの行番号を表示(nオプション):

gred.py n "/port scan/" example.log

sed風の置換コマンド(s///)を使う

s/正規表現/置換文字列/
iオプション、nオプション、Hオプションが使用可能。
置換処理された文字列が標準出力に出力される。
置換は各行に対してグローバルに行われる。
置換が行われなかった行も、すべて表示される(置換が行われた行のみ表示、という動作はない)。
置換文字列は、Pythonの文字列エスケープルールにしたがって解釈される(Pythonは、定義されていないエスケープを発見した場合、エスケープ文字(\)を削除せずに残す)。ただし、例外的にスラッシュのエスケープ(\/)だけはこのスクリプトによって処理され、リテラルのスラッシュ文字(/)に置き換わる。

ログ中の「tcp/80」という表現を、「http」に置換:

gred.py "s/tcp\/80/http/" example.log > replaced_example.log
  • スラッシュ記号(/)はバックスラッシュ(\)でエスケープする。

ログ中の「tcp/80」という表現を、「80/tcp」に置換:

gred.py "s/(tcp)\/(80)/\2\/\1/" example.log > replaced_example.log
  • 置換文字列内でも、\numberで後方参照が使える。re モジュールの re.sub() に渡して処理させているだけなので、置換文字列内だけで有効な \g<number> も使える。