tse - pythonによるテキスト整形ユーティリティ

32
tse Text Stream Editor Python ににに ににににににににににににに 2015/10/10 PyCon JP 2015 Atsuo Ishimoto

Upload: atsuo-ishimoto

Post on 06-Jan-2017

18.451 views

Category:

Career


0 download

TRANSCRIPT

Page 1: tse - Pythonによるテキスト整形ユーティリティ

tse Text Stream Editor

Python によるテキスト整形ユーティリティ2015/10/10 PyCon JP 2015Atsuo Ishimoto

Page 2: tse - Pythonによるテキスト整形ユーティリティ

自己紹介

2

いしもと石本 敦夫あつお

python.jp ドメインの管理者@atsuoishimoto著書

Python ライブラリ厳選レシピPython 文法詳解パーフェクト Python

Page 3: tse - Pythonによるテキスト整形ユーティリティ

Unix のテキスト処理といえば

3

sed, awk, perl などのワンライナーが定番Python でもワンライナーを書きたい使い慣れたモジュール群を手軽に活用したいいちいちスクリプトファイルを作成したくないシェルのヒストリーから呼び出したい

Page 4: tse - Pythonによるテキスト整形ユーティリティ

4

Python はワンライナー向き?向きません

インデントと改行が必須sys, re などの import など、タイプ量が多いワンライナー用のコマンドラインオプションがない (Python2) Unicode(Encode|Decode)Error$ python -c 'print u" あ "'|less 等。。。

Page 5: tse - Pythonによるテキスト整形ユーティリティ

5

tse Text Stream Editor

Python によるテキスト整形ツールPython スクリプトをコマンドラインで指定一般的なモジュール (sys, re など ) の自動インポートファイルを読み込み、スクリプトを実行入出力エンコーディングの指定

Page 6: tse - Pythonによるテキスト整形ユーティリティ

6

インストール方法pip install tse

Python2.7 以降Python3.3 以降

Page 7: tse - Pythonによるテキスト整形ユーティリティ

7

tse の動作 1 . テキストファイルを一行ずつ読み込み、 2. 行に一致するパターンがあれば、 3. 行を変数に代入し、 4. 対応するアクションを実行する

Page 8: tse - Pythonによるテキスト整形ユーティリティ

8

$ tse -s '^\d+' 'print(L.lower())' \ -s '^\w+' 'print(L.upper())'

パターンとアクションパターン 入力行を検索する、正規表現式アクション パターンの検索が成功した時に実行するスクリプト

パターン アクション-s オプションで指定

Page 9: tse - Pythonによるテキスト整形ユーティリティ

9

サンプル'spam' を含む行を、小文字に変換して出力tse -s "spam" "print(L.lower())" < s.txt

Page 10: tse - Pythonによるテキスト整形ユーティリティ

10

サンプル行ごとに、すべての数字列の和を出力

tse -s ".*" "print(sum(int(s) for s in re.findall(r"\d+", L)))"" < s.txt

Page 11: tse - Pythonによるテキスト整形ユーティリティ

11

パターン

例• spam|ham 'spam' または 'ham' を含む行 • ^\d+ 数字列で始まる行

re モジュールを利用入力テキストを検索する正規表現式

Page 12: tse - Pythonによるテキスト整形ユーティリティ

12

アクション例• print('hello') 'hello' と出力• print(L.upper()) 行を大文字に変換して出力

パターンがヒットした行で実行するスクリプト

Page 13: tse - Pythonによるテキスト整形ユーティリティ

13

複数行のアクション

例$tse -s '^\w' 'if L:' ' print(L)' < spam.txt

パターンには複数のアクションを指定できる。 2 番目以降のアクションは、先頭のアクションの次の行として実行される。

if L: print(a)

Page 14: tse - Pythonによるテキスト整形ユーティリティ

14

インデント$ tse -s '.*' 'if len(L)>5:{{print(1)}}'

{{ と }} でインデントするブロックを指定する

if len(L)>5: print(1)

文字列・コメント中の "{{}}" はインデントとして扱わない例 ) 'print("{{spam}}{{ham}}")

Page 15: tse - Pythonによるテキスト整形ユーティリティ

15

入力ファイルの指定-s オプションに続けてファイル名を指定するときは、オプションとファイル名を -- で区切る

ファイル名が - のときは、標準入力から読み込む$tse -s '^\d' 'print(S)' -- a.txt b.txt

$tse -s '^\d' 'print(L)' -- -

Page 16: tse - Pythonによるテキスト整形ユーティリティ

16

変数処理中のテキストは、変数に格納される変数名 内容L 現在処理中のテキスト行全体L0 テキスト行を空白で区切った文字列

の配列L1, L2,... テキスト行を空白で区切った文字列

の 1 番目、 2 番目、…N L0 の長さ

Page 17: tse - Pythonによるテキスト整形ユーティリティ

17

マッチ文字列正規表現にマッチした文字列も変数に格納変数名 内容S 正規表現にマッチしたグループの配列S0 正規表現にマッチした部分文字列全

体S1, S2,... () で囲んだグループの部分文字列グループ名 '(?P< グループ名 >)' で指定したグ

ループの部分文字列M Re モジュールの Match オブジェクト

Page 18: tse - Pythonによるテキスト整形ユーティリティ

18

変数のサンプル$ echo 'ab cd ef'| tse -s '.*' 'print(L3, L2, L1)'ef cd ab

空白区切りの単語を出力

$ echo '123abc' \| tse -s '(?P<num>\d+)(.*)' 'print(num, S2)'123 abc

パターンの部分文字列

Page 19: tse - Pythonによるテキスト整形ユーティリティ

19

変数のサンプル$ls -l|tse -s '' 'if N>2 and int(L5)>=1024:print(L9)'

サイズ >=1024のファイル名を出力

$ ls -ltotal 168-rw-r--r-- 1 ishimoto staff 698 10 6 12:58 HISTORY-rw-r--r-- 1 ishimoto staff 1064 10 6 12:39 LICENSE-rw-r--r-- 1 ishimoto staff 35 10 6 12:39 MANIFEST.in

1 2 3 4 5 6 7 8 9

Page 20: tse - Pythonによるテキスト整形ユーティリティ

20

その他の変数変数名 内容FILENAME 処理中のファイル名。標準入力の場

合は '<stdin>'LINENO 処理中の行番号 (1, 2, 3,…)

Page 21: tse - Pythonによるテキスト整形ユーティリティ

21

省略時のパターン

$ tse -s '' 'print(L)'

パターンが空文字列の場合、 '.*' と同じ

$ tse -s '.*' 'print(L)'

Page 22: tse - Pythonによるテキスト整形ユーティリティ

22

省略時のアクション

$ tse -s '.*' ''

アクションが空文字列の場合、 'print(L)' と同じ

$ tse -s '.*' 'print(L)'

Page 23: tse - Pythonによるテキスト整形ユーティリティ

23

begin アクションと end アクション--begin オプション 起動直後に実行するアクション--end オプション ファイル読み込み終了後に実行するアクション$ tse --begin 's=0' \ --end 'print(s)' \ -s '.*' 's+=len(L)' *.txt

例 ) *.txt ファイル全文字数を出力する

Page 24: tse - Pythonによるテキスト整形ユーティリティ

24

インポート済みモジュール$ tse -s '.*' 'os.mkdir(L)'

sys, re, os, os.path はインポート不要

os.path は、 from os import path 形式$ tse -s '.*' 'print(path.splitext(L)[1])'

Page 25: tse - Pythonによるテキスト整形ユーティリティ

25

モジュールのインポート--module/-m オプション

実行前にモジュールをインポートする例 ) $tse -m math --begin 'print(math.sqrt(2))'

--module-star/-ms オプションfrom モジュール名 import * 形式でインポートする例 ) $tse -ms math --begin 'print(sqrt(2))'

Page 26: tse - Pythonによるテキスト整形ユーティリティ

26

エンコーディング指定--input-encoding/-ie オプション

入力ファイルのエンコーディングを指定する例 ) $tse -ie cp932 -s '' ''

--output-encoding/-oe オプション出力ファイルのエンコーディングを指定する例 ) $tse -ie cp932 -s '' ''

Page 27: tse - Pythonによるテキスト整形ユーティリティ

27

--inplace オプション入力ファイルを、出力で上書きする。

$tse --inplace .bak -s '' 'print(L.lower())' -- spam.txt

元のファイルは、指定した拡張子を付加したファイルに保存

Page 28: tse - Pythonによるテキスト整形ユーティリティ

28

--script-file/-f オプション起動前に実行するスクリプトファイルを指定する。

$tse -f scr.py -s '' '' < spam.txt

デフォルトでは、 ~/.tserc ファイルが存在すれば実行する。

Page 29: tse - Pythonによるテキスト整形ユーティリティ

29

拡張子ごとにファイルサイズ集計$ find . -type f | \tse -ms collections -b 'c=defaultdict(int)' \-s '' 'c[path.splitext(L)[1]]+=path.getsize(L)' \-e 'for r in c.items():print(r)'

Page 30: tse - Pythonによるテキスト整形ユーティリティ

30

ip アドレスからホスト名逆引き$ cat log | tse -ms socket -s '' \'try:print(gethostbyaddr(L1)[0], L1)' \'except:print("unknown", L1)'

Page 31: tse - Pythonによるテキスト整形ユーティリティ

31

HTML から a 要素を抽出$ curl www.python.jp | tse -ms 'bs4' -b 'for a in BeautifulSoup(sys.stdin.read(), "lxml").find_all("a"):{{url=a.get("href", ""){{}}if url.startswith("http"):print(a["href"])'

Page 32: tse - Pythonによるテキスト整形ユーティリティ

32

ご清聴ありがとうございました