正規表現リテラルは本当に必要なのか?

61
copyright© 2014 kuwata-lab.com all rights reserved 正規表現リテラルは 本当に必要なのか? Makoto Kuwata [email protected] http://www.kuwata-lab.com/ PyConJP 2014 ver 1.1 (2014-09-17): スライドを追加・加筆

Upload: kwatch

Post on 19-Nov-2014

1.358 views

Category:

Technology


5 download

DESCRIPTION

PyConJP2014発表資料。 ・正規表現リテラルは、**あれば便利だけどなくても困らない**(ライブラリでカバーできる)ことを説明する。 ・Pythonの正規表現が抱える問題点とその解決案を紹介する。

TRANSCRIPT

Page 1: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

正規表現リテラルは本当に必要なのか?

Makoto [email protected]

http://www.kuwata-lab.com/

PyConJP 2014

ver 1.1 (2014-09-17): スライドを追加・加筆

Page 2: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

発表の背景✓ 2013年末、プログラミング言語における「正規表現リテラルの必要性」が支持を集めるhttp://togetter.com/li/603521

http://blog.kazuhooku.com/2013/12/blog-post.html  

✓ Pythonは正規表現リテラルがないけど、別に困ってないよ?…と説明しても聞いちゃくれないPerler/Rubyist/JavaScripterと、正規表現リテラルがなくて困ってるJavaユーザと、どんなときでも叩かれるPHPerが入り乱れた、異種言語間お笑いバトル

Page 3: 正規表現リテラルは本当に必要なのか?

え|マジ

リテラルないの?

正規表現

のはPHPまでだよね!

あれなしで許される

キモ|イ

キャハハ

ハハハハ

Pythonの評判

Page 4: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

発表の目的✓ 正規表現リテラルは、あれば便利だけどなくても困らない(ライブラリでカバーできる)ことを説明する

✓ Pythonの正規表現ライブラリが抱える問題点とその解決案を紹介する

Page 5: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

発表の対象者✓ Pythonのことをよく知らないPerlerやRubyistやJavaScripter 

✓ 他言語との違いが気になるPythonista

✓ 二重バックスラッシュにイライラしてるJavaユーザ

Page 6: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

第1部:正規表現リテラルに関する誤解

Page 7: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

第1部:正規表現リテラルに関する誤解

✓ 誤解:正規表現リテラルがあったほうが書きやすい✓ 誤解:正規表現リテラルがあったほうが性能がよい✓ 誤解:正規表現のほうが文字列関数より学習コストが低い

Page 8: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

第1部:正規表現リテラルに関する誤解

✓ 誤解:正規表現リテラルがあったほうが書きやすい✓ 誤解:正規表現リテラルがあったほうが性能がよい✓ 誤解:正規表現のほうが文字列関数より学習コストが低い

Page 9: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

## 正規表現リテラルあり/[a-z]+/.exec(string) # JavaScript

## 正規表現リテラルなし(new RegExp("[a-z]+")).exec(string) # JavaScript

正規表現リテラルがあると、正規表現は書きやすい?

Page 10: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

## 正規表現リテラルなしfunction re(pattern) { # JavaScript return new RegExp(pattern);}re("[a-z]+").exec(string)

正規表現リテラルがなくても、正規表現を書きやすくできる

関数やライブラリで解決できる

Page 11: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

## 正規表現リテラルあり/^\d\d:\d\d$/ # JavaScript

## 正規表現リテラルなしnew RegExp("^\\d\\d:\\d\\d$") # JavaScript

二重バックスラッシュ問題を発生させないためには正規表現リテラルが必要?

Page 12: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

## JavaScriptnew RegExp('^\d\d:\d\d:\d\d$')

## Pythonre.match(r"^\d\d:\d\d:\d\d$", timestr)

## PHPpreg_match('/^\d\d:\d\d:\d\d$/', timestr)

raw文字列リテラル (Python) やシングルクォート(JS, PHP)でも発生しない

Page 13: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

## Javaimport java.util.regex.Pattern;import java.util.regex.Matcher;Pattern pat = Pattern.compile("^\\d\\d:\\d\\d$");Matcher m = pat.matcher(timestr);

二重バックスラッシュが辛いです ;(

ただしraw文字列相当のない言語、お前はダメだ

Page 14: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

【問題点】Javaで正規表現が書きにくい(二重バックスラッシュがつらい)

【解決策】正規表現リテラル

【解決策】raw文字列リテラル

導入すると、言語仕様が肥大化してしまう

正規表現以外にも利用可能、かつ言語仕様が肥大化しない

Page 15: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

## JavaPattern pat = Pattern.compile(r"^\d\d\d\d$");Matcher m = pat.matcher(input);

raw文字列リテラルがほしいけど、言語仕様を拡張しないと無理じゃん ;(

とはいえ、raw文字列リテラルを導入するには言語仕様の拡張が必要

Page 16: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

## 先行事例: Cのprintf()やJavaのString.format()String.format("s=%s, n=%d", s, n);

そもそも、バックスラッシュでないとだめなん?

メタキャラクタとして「%」を使っている!二重バックスラッシュのような問題がない!

Page 17: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

## http://kwatch.houkagoteatime.net/blog/2013/12/28/java-regex/import static benry.rexp.Rexp.rexp;import benry.rexp.Matched;

String pat = "^(`d`d`d`d)-(`d`d)-(`d`d)$";Matched m = rexp(pat).match(str);if (m != null) { System.out.println(m.get(1));}

「\」のかわりに「`」を使ってる(変更も可能)

バックスラッシュ以外を使えば、Javaでも正規表現が書きやすくなる! (最初は違和感あるけど慣れの問題)

Page 18: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

【問題点】Javaで正規表現が書きにくい(二重バックスラッシュがつらい)

【解決策】正規表現リテラル

【解決策】raw文字列リテラル

言語仕様の変更が必要なく、ライブラリだけで実現可能

【解決策】バックスラッシュをやめる

Page 19: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

✓ 正規表現リテラルのないJavaでは、正規表現が書きにくい

✓ 正規表現リテラルのあるPerlやRubyでは、正規表現が書きやすい

✓ だから、プログラミング言語に正規表現リテラルは必要だ!

・問題:解決方法 = 1:N・one of themでしかない方法を、only oneな方法だと勘違いしてる

(*注) もちろん、複数の解決方法の間では優劣が存在する。この場合なら、「正規表現リテラルが必要」と主張するには、それが他の方法より優れていることを説明する必要がある。

(*注)

← わかる

← わかる

← その理屈はおかしい

Page 20: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

ここまでのまとめ✓ 正規表現を書きやすくする言語機能は、ひとつではない正規表現リテラル、raw文字列リテラル

✓ 正規表現リテラルよりraw文字列リテラルのほうが望ましい正規表現以外にも利用可能だし、言語仕様も肥大化しない

✓ そもそも、バックスラッシュを使わなければいい言語仕様の拡張が必要ないので、今すぐ使える方法

Page 21: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

第1部:正規表現リテラルに関する誤解

✓ 誤解:正規表現リテラルがあったほうが書きやすい✓ 誤解:正規表現リテラルがあったほうが性能がよい✓ 誤解:正規表現のほうが文字列関数より学習コストが低い

Page 22: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

## Ruby100.times do filename =~ /\.(png|gif|jpe?g)$/end

正規表現リテラルなら、コンパイルは1度だけ

100回コンパイルされたりはしない(ただし埋め込み式のある場合は別)

Page 23: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

## Pythonfor _ in range(100): re.search(r'\.(png|gif|jpe?g)', filename)

正規表現リテラルがない場合はどうなる?

re.search() の中で毎回コンパイルされてそうだから、遅いのでは?

Page 24: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

## Python_cache = {}

def _compile(patstr): ## キャッシュがあればそれを返す try: return _cache[patstr] except KeyError: pass ## なければコンパイルして ## キャッシュする pat = sre_compile(patstr) _cache[patstr] = pat return pat

ライブラリがキャッシュすれば無問題

def search(patstr, s): pat = _compile(patstr) return pat.search(s)

def sub(patstr, rep, s): pat = _compile(patstr) return pat.sub(rep, s)

注:実際の正規表現ライブラリ (re.py) では、正規表現フラグつきでキャッシュしたり、キャッシュが大きくなりすぎるとパージするなど、もっと複雑である。

キャッシュを活用他の関数は _compile() を呼び出す

Page 25: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

## Pythonrexp = re.compile(r'\.(png|gif|jpe?g)')for _ in range(100): re.search(rexp, filename)

キャッシュから取り出すオーバーヘッドがなくなる(通常は気にするほどではない)

どうしても気になる場合は、正規表現オブジェクトを変数で保持すればよい

Page 26: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

なおCPythonでは、正規表現ライブラリより文字列関数のほうがかなり速い

startswith()

endswith()

isdigit()

文字列関数 正規表現

文字列関数の速度を100としたときのグラフ

https://gist.github.com/kwatch/f923fb5a71da3f69eccbhttps://gist.github.com/kwatch/0132268e0c38741fe59ahttps://gist.github.com/kwatch/e1bc95fcc6cb75c60c94

Page 27: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

// Rust (http://doc.rust-lang.org/regex/)

#![feature(phase)]#[phase(plugin)]extern crate regex_macros;extern crate regex;

fn main() { let re = regex!(r"^\d{4}-\d{2}-\d{2}$"); assert_eq!(re.is_match("2014-01-01"), true);}

また正規表現に対する高度な最適化は、リテラルの有無ではなく、処理系の評価戦略次第

正規表現文字列をコンパイル時に評価→ 正規表現リテラルがなくても コンパイル時に間違いを検出→ 正規表現リテラルがなくても バイナリを生成可能

Page 28: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

ここまでのまとめ✓ キャッシュを使えば、正規表現が毎回コンパイルされることはない正規表現リテラルがなくても充分な性能は出せる

✓ 正規表現より文字列関数のほうが高速少なくともCPythonではそう

✓ リテラルがなくても正規表現のコンパイル時評価は可能「リテラルの有無」と「処理系の評価戦略」は、基本的に別個の話

Page 29: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

第1部:正規表現リテラルに関する誤解

✓ 誤解:正規表現リテラルがあったほうが書きやすい✓ 誤解:正規表現リテラルがあったほうが性能がよい✓ 誤解:正規表現のほうが文字列関数より学習コストが低い

Page 30: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

✓ そもそも、「正規表現リテラルは必要か?」と「正規表現と文字列関数はどちらが学習コストが低いか?」は別の話仮に「正規表現のほうが文字列関数よりわかりやすい」という結論になったとしても、それをもって「正規表現リテラルは必要」とはならない

✓ そのうえで、あえて「どちらが学習コストが低いか?」を論じる。

Page 31: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

## 正規表現 re.match(r"^\d+$", input)re.match(r"^http://", string)re.search(r"\.(png|gif|jpg)$", filename)

## 文字列関数input.isdigit()string.startswith("http://")filename.endswith((".png", ".gif", ".jpg"))

文字列関数で済む範囲であれば、正規表現より文字列関数のほうが読みやすい、わかりやすい

初級者でもわかりやすい!

毎日コード書いてる人なら覚えられるだろうけど・・・

Page 32: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

## Rubystring =~ /\.html$/

## Rubystring.end_with?(".html")

また正規表現は落とし穴も多いので、初級者にはつらいことも

初級者でも間違えない!

厳密には間違い(正解は /\.html\z/ )

Page 33: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

## 正規表現pat = r"^(\d{4})-(\d\d)-(\d\d)[ T](\d\d):(\d\d):\d\d)$"re.match(pat, input)

とはいえ、上達するにつれ、正規表現を避けることはできない

文字列関数でこれを書くのはつらい

Page 34: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

正規表現だけ 正規表現+文字列関数

学習コストの内訳(ソース:個人的印象)

正規表現 正規表現

文字列関数

正規表現の学習コストに比べたら、文字列関数のそれは大したことない(単機能ばかりだから)

Page 35: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

“正規表現リテラルがあれば文字列関数を減らせるし、処理系も単純にできるよ!”

コア言語仕様を肥大化させてでも文字列関数を減らすことがそんなに重要なの?

それ正規表現リテラルじゃなくて正規表現のメリットじゃないの?

誰にとってのメリットなの?ときどきしかコードを書かないライトユーザにも嬉しいことなの? (科学者、統計学者、CGデザイナ、etc)

そんな簡単な話ではないはず・・・

「/..../」のパースは単純なの?文字列関数が減るかわりに別の複雑さが増えてない?

Page 36: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

ここまでのまとめ✓ 文字列関数だけのほうが学習コストは低い学習コスト: 正規表現 >>> 文字列関数

✓ とはいえ正規表現の勉強はどのみち必要学習コスト: 正規表現 < 文字列関数+正規表現

✓ 正規表現やリテラルの得失は一概には言えないだれにとってのメリット?どのくらいのメリット?

✓ そもそも「正規表現リテラルの得失」と「正規表現の得失」は別の話ちゃんと分けて議論しましょう

Page 37: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

第2部:Python正規表現ライブラリの問題点と解決案

Page 38: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

第2部:Python正規表現ライブラリの問題点と解決案

✓ re.match()とre.search()の2つがある✓ ライブラリの使い方が2系統ある✓ 正規表現がいつもキャッシュされてしまう✓ 連続したマッチングとif文との相性が悪い

Page 39: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

第2部:Python正規表現ライブラリの問題点と解決案

✓ re.match()とre.search()の2つがある✓ ライブラリの使い方が2系統ある✓ 正規表現がいつもキャッシュされてしまう✓ 連続したマッチングとif文との相性が悪い

Page 40: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

re.match()は先頭からのマッチングしかできない、re.search()なら途中からのマッチングも可## これはマッチするre.match(r"(\d+)", "123abc")re.search(r"(\d+)", "abc123")

## これはマッチしない!(先頭にないので)re.match(r"(\d+)", "abc123")

re.match(r"pat", str) は re.search(r"^pat", str) で代用できる。re.match() は混乱のもとだし、いらないのでは?

Page 41: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

第2部:Python正規表現ライブラリの問題点と解決案

✓ re.match()とre.search()の2つがある✓ ライブラリの使い方が2系統ある✓ 正規表現がいつもキャッシュされてしまう✓ 連続したマッチングとif文との相性が悪い

Page 42: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

Pythonの正規表現ライブラリは、使い方が2系統存在する

大抵の正規表現操作が、モジュールレベルの関数と、 コンパイル済み正規表現のメソッドとして提供されることに注意して下さい。関数は正規表現オブジェクトのコンパイルを必要としない近道ですが、いくつかのチューニング変数を失います。

”引用元: http://docs.python.jp/3.3/library/re.html

re.xxxx() 系re.compile().xxxx() 系

追加スライド

Page 43: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

しかも、両者は似ているようで微妙に違う ;(これは困る

## re.compile().xxxx() 系re.compile(pat, flags).match(string, pos, endpos)re.compile(pat, flags).sub(repl, string, count)

## re.xxxx() 系re.match(pat, string, flags)re.sub(pat, repl, string, count, flags)

re.sub() は、 Python2.6では正規表現フラグが指定できなかった

追加スライド

開始位置と終了位置が、re.compile().match() では指定できるが re.match() ではできない

Page 44: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

ところで re.xxxx() のやっていることは、内部で re.compile().xxxx() を呼び出しているだけdef compile(pattern, flags=0): return _compile(pattern, flags)

def match(pattern, string, flags=0): return _compile(pattern, flags)\ .match(string)

def sub(pattern, repl, string, count=0, flags=0): return _compile(pattern, flags)\ .sub(repl, string, count)

Page 45: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

だったら、全部 re.compile().xxxx() を使うようにすれば、re.xxxx() をなくして一本化できるよね?

rx = re._compile

## マッチングm = re.match(r"(\d+)", "123abc") # beforem = rx(r"(\d+)").match("123abc") # after

## 文字列置換re.sub(r"\.gif$", ".png", filename) # beforerx(r"\.gif$").sub(".png", filename) # after

re.compile()へのショートカット

Page 46: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

一本化できれば、「似てるけど微妙に違う2系統」が共存しなくてすむ## re.compile().xxxx() 系re.compile(pat, flags).match(string, pos, endpos)re.compile(pat, flags).sub(repl, string, count)

## rx().xxxx() 系rx = re._compilerx(pat, flags).match(string, pos, endpos) rx(pat, flags).sub(repl, string, count)

等価 (当然)

追加スライド

Page 47: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

また1つの関数に5~6個も引数があるくらいなら、2~3個の関数2つに分けたほうがわかりやすい

## beforere.sub(pattern, repl, string, count=0, flags=0)

## afterrx(pattern, flags=0).sub(repl, string, count=0)

引数が5個!

引数2個と 引数3個

Page 48: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

第2部:Python正規表現ライブラリの問題点と解決案

✓ re.match()とre.search()の2つがある✓ ライブラリの使い方が2系統ある✓ 正規表現がいつもキャッシュされてしまう✓ 連続したマッチングとif文との相性が悪い

Page 49: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

re.compile() は正規表現を必ずキャッシュする、けどキャッシュする必要がないときもあるclass HTMLHelper(object): _ESCAPE = re.compile(r"[&<>\"']")

クラス変数に保持しているので、ライブラリ側でキャッシュする必要はない(けど強制的にキャッシュされるので、 キャッシュが必要以上に肥大化する)

Page 50: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

特に、たくさんの正規表現がデータとして与えられると、キャッシュが無駄に肥大化してしまうurlpatterns = patterns('', url(r'^posts/$', "..."), url(r'^posts/new$', "..."), url(r'^posts/(?P<id>\d+)$', "..."), url(r'^posts/(?P<id>\d+)/comments$', "..."), url(r'^posts/(?P<id>\d+)/edit$', "..."), ... )

コンパイルするとすべて強制的にキャッシュされる→ キャッシュする必要のないデータによって  キャッシュが肥大化する

Page 51: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

Pythonの正規表現ライブラリは、キャッシュが肥えすぎるとすべてパージしてしまう!_cache = {}_MAXCACHE = 512

def _compile(pattern, flags): ...(snip)... p = sre_compile.compile(pattern, flags) if not bypass_cache: if len(_cache) >= _MAXCACHE: _cache.clear() _cache[type(pattern), pattern, flags] = p return p

キャッシュが肥大化する→ キャッシュがパージされる→ 性能低下 ;(

Page 52: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

キャッシュせずにコンパイルする機能が、公式に用意されるとうれしいclass HTMLHelper(object): _ESCAPE = re.sre_compile.compile(r"[&<>\"']")

これならキャッシュしないので、キャッシュの無駄な肥大化を防げる(しかしunofficialなので使用には注意すること)

Page 53: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

第2部:Python正規表現ライブラリの問題点と解決案

✓ re.match()とre.search()の2つがある✓ ライブラリの使い方が2系統ある✓ 正規表現がいつもキャッシュされてしまう✓ 連続したマッチングとif文との相性が悪い

Page 54: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

複数の正規表現にマッチさせるとき、こう書きたい

## ほんとはこう書きたい

if m = re.match(pat1, text): x, y = m.groups()elif m = re.match(pat2, text): y, z = m.groups()elif m = re.match(pat3, text): z, x = m.groups()

文法エラー:Pythonでは代入文は式ではないので、if文の条件式には書けない

Page 55: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

でもPythonではこう書くしかない

m = re.match(pat1, text)if m: x, y = m.groups()else: m = re.match(pat2, text) if m: y, z = m.groups() else: m = re.match(pat3, text) if m: z, x = m.groups()

if文のネストが深くなる

Page 56: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

関数+return や、while文+break という手もあるが、あまり嬉しくはないwhile 1: m = re.match(pat1, text) if m: x, y = m.groups() break m = re.match(pat2, text) if m: y, z = m.groups() break m = re.match(pat3, text) if m: z, x = m.groups() break break

if文のネストは減ったけど、トリッキーで間違えやすい

Page 57: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

そこで、こういう機能はどうでしょう?

m = re.matching(text)

if m.match(pat1): x, y = m.groups()elif m.match(pat2): y, z = m.groups()elif m.match(pat3): z, x = m.groups()

マッチングの対象文字列とマッチング結果を保持するようなオブジェクトを用意すれば、

連続したマッチングが素直に書けるはず

Page 58: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

実装はこちら

class matching(object): def __init__(self, string): self.string = string self.matched = None

def match(self, pattern, flags=0): self.matched = re.compile(pattern, flags)\ .match(self.string) return self.matched

def groups(self, *args): return self.matched.groups(*args)

http://bit.ly/matching_py

Page 59: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

Questions?

Page 60: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

おまけ: benry.rexpfrom benry.rexp import rx

## re.compile() へのショートカットm = rx(r'pat', rx.I).match(string, start, end)

## キャッシュせずにコンパイルrexp = rx.compile(r'pat', rx.I)

## 連続したマッチングm = rx.matching(string)if m.match(r'^(\d\d\d\d)-(\d\d)-(\d\d)$'): Y, M, D = m.groups()else m.match(r'(\d\d)/(\d\d)/(\d\d\d\d)$'): M, D, Y = m.groups()

https://pypi.python.org/pypi/benry

Page 61: 正規表現リテラルは本当に必要なのか?

copyright© 2014 kuwata-lab.com all rights reserved

おしまい