このBlogは移転しました。今後は aish.dev を御覧ください。

tse - Text Stream Editor in Python

久々にsedを使ってちょっとしたテキストを処理をしてたら、やっぱりこういうのもPythonで出来ないかなぁ思った訳である。Pythonスクリプトというのは改行とインデントが不可欠なので One Liner に向かないというのはご案内の通りだが、ちょっとは何とかなるんでないか。

昔、私がPythonを使い始めた頃のPythonはとことんOne Linerに向いていなくて、そんなこと考える自体時間の無駄だったが、今はだいぶ状況が違う。文字列にはちゃんとメソッドがあるし、リスト内包も使える。AWKみたいなマッチング機能とあわせて使えるようにすれば、意外と使い物になるんではないかというアイデアだ。

作ってみると、結構簡単にプロトタイプができた。

http://pypi.python.org/pypi/tse

tse ではAWKのように、条件と条件が満たされた時に実行される処理のペアを

tse -s CONDITION1 ACTION1 -s CONDITION2 ACTION2 ...

のような形式で指定する。


例えばこんな感じだ。

$ cat testfile | tse -s "^\D+" "print L" -s "^\d+" "print S0"

このサンプルでは、二つの -s オプションが指定されていて、最初のオプションは

"^\D+" "print L"

となっている。最初の ^\D+ は「数字以外の文字で始まる文字列」を示す正規表現式であり、この条件にマッチする行では、アクション print L が実行される。アクションはPythonステートメントで、この例ではPythonのprintステートメントである。Lは現在の行を格納する変数で、AWKでは $0に相当する。

2番目の

"^\d+" "print S0"

では、条件として正規表現 ^\d+ を指定している。これは「数字で始まる文字列」を示す正規表現で、print S0 は条件式にマッチした文字列を出力するアクションだ。S0 は条件式にマッチした部分文字列の変数である。

次の例は、カレントディレクトリに含まれているファイルの拡張子一覧を取得している。

 find . -type f|tse -s ".*" "print path.splitext(L)[1]"|sort|uniq

いちいち正規表現を書いてファイル名から拡張子を取り出そうとすると面倒なものだが、ここではPythonの標準モジュール os.path.splitext()を使ってあっさりと取得している。osモジュールは起動時に自動的にimportされるので、インポート処理を記述する必要はない。sys, os, reモジュールは自動的にインポートされるようになっている。

2012/2/12 - tse 0.0.2にあわせてコマンドライン引数を修正