トップ 一覧 検索 ヘルプ RSS ログイン

grep風テキスト処理ツール.pyの変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
{{category Python}}

!!!gred.py
{{ref gred.py.txt}}

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

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