正規表現あれこれ
この記事は Python Tips Advent Calendar 2012 24日目の記事です。
Python の正規表現には、便利な機能がいくつかあります。ということで、いくつか見ていきましょう。
コメント機能
>>> import re >>> re.compile(r''' ... ^ # start of a line ... \[font # the font tag ... (?:=(?P<size> # optional [font=+size] ... [-+][0-9]{1,2} # size specification ... ))? ... \] # end of tag ... (.*?) # text between the tags ... \[/font\] # end of the tag ... ''', re.VERBOSE) #doctest: +ELLIPSIS <_sre.SRE_Pattern object at 0x...>
このように VERBOSE フラグを付けるとコメントが付けらます。
VERBOSE フラグは、空白と # 以降の文字列を無視するようになります。もし空白や # を使いたい場合は \# のようにエスケープする必要があります。
デバッグモード
>>> import re >>> re.compile(r'^\[font(?:=(?P<size>[-+][0-9]{1,2}))?\](.*?)[/font]', re.DEBUG) #doctest: +ELLIPSIS at at_beginning literal 91 literal 102 literal 111 literal 110 literal 116 max_repeat 0 1 subpattern None literal 61 subpattern 1 in literal 45 literal 43 max_repeat 1 2 in range (48, 57) literal 93 subpattern 2 min_repeat 0 65535 any None in literal 47 literal 102 literal 111 literal 110 literal 116 <_sre.SRE_Pattern object at 0x...>
このように、どんな状態機械になったのかが標準出力に出力されるので、デバッグが容易になります。
置換時に関数を渡す
sub 関数を使って置換する場合、通常は文字列を指定しますが、関数を指定することもできます。
>>> import re >>> re.sub('ab|bb', \ ... lambda m: 'xxx' if m.group(0) == 'ab' else 'yyy', \ ... 'aaabbb') 'aaxxxyyy'
このように関数を渡すと、文字列がマッチするたびに関数が呼ばれます。
引数には MatchObject が渡され、どの文字列に一致したかなどの情報が取れます。
複数の文字列置換
sub 関数は、例えば複数の文字列を置換する場合に役立ちます。
例えば html のエスケープなどで普通に replace 関数を使った場合、以下の様な問題に遭遇することがあります。
>>> text = '<hoge>&&&</hoge>' >>> text.replace('<', '<') \ ... .replace('>', '>') \ ... .replace('&', '&') '&lt;hoge&gt;&&&&lt;/hoge&gt;'
'<' を '<' に置換した後、'&' を '&' に置換しているので '&lt;' になっています。これは意図した動作では無いでしょう。
この場合であれば '&' の置換を先頭にやれば一応動作はしますが、そのような順序に依存した変換はバグが発生しやすくなってしまいます。
これは sub の引数に関数を指定することで簡単に一括で置換できます。
>>> def multiple_replace(text, dic): ... if len(dic) == 0: ... return text ... import re ... return re.sub('|'.join(map(re.escape, dic)), ... lambda m: dic[m.group(0)], ... text) >>> multiple_replace('<hoge>&&&</hoge>', { ... '<': '<', ... '>': '>', ... '&': '&' }) '<hoge>&&&</hoge>'
それぞれの置換対象の文字列を '|' で繋いでどれかにマッチさせるようにして、そのマッチした文字列からどの文字列に置換したいかを指定しています。
Python の正規表現はちゃんと使うとかなり便利になるので、一度は re のドキュメントを全部読んでおいた方がいいでしょう。
.