Engineer as a Lifestyle @tenkoma

What We Find Changes Who We Become -- Peter Morville著『アンビエント・ファインダビリティ 』

正規表現その2

http://www.python.jp/Zope/articles/tips/regex_howto/regex_howto_4の途中から最後の章まで読んだ.
2つ疑問がでてきた.
まず,グルーピングした表現にマッチした文字列を取り出すとき,複数マッチした文字列のリストをとりだしたいときはどうすればいいのだろう?Pythonクィックリファレンスのp.200〜201で解決した.グルーピングに限らず,findallメソッドを使えばいい.文字列から正規表現にマッチした部分を取り出すメソッドが3つある.rが正規表現オブジェクトだとして次のような違いがある.
matchメソッドとsearchメソッドはマッチした結果のなかで一番左の部分文字列を返すが,

r.match
string文字列のインデックス(start引数)の位置からマッチしないと結果がかえってこない.たとえば
>>> r = re.compile('class')
>>> r.match('classtree').group()
'class'
>>> r.match('subclass').group()

Traceback (most recent call last):
  File "<pyshell#47>", line 1, in -toplevel-
    r.match('subclass').group()
AttributeError: 'NoneType' object has no attribute 'group'

例外はmatchメソッドの戻り値がNoneであり,group属性が見つからないことを表す.

r.search
start引数の位置からマッチしなくても,最初に見つかった部分文字列のマッチオブジェクトを返す.
>>> r = re.compile('class')
>>> r.search('classtree').group()
'class'
>>> r.search('subclass').group()
'class'

(start引数は文字列中のどの位置から検索を始めるかを指定するがこのコード例ではdefaultで0になっている)
このように微妙な違いがある.

findall
マッチしたすべての結果をリストに入れて返す.
>>> r = re.compile(r'\b\w+class\b')
>>> r.findall('subclass superclass')
['subclass', 'superclass']

よく読み返してみたらmatchとsearchの違いを簡潔に表にしたものが見つかった.一遍よんでるはずなのに,わかったつもりになってるとはこのことだな…orzうひ,最後のページにも…こっちはまだ読んでなかったみたいだ.
二つ目.http://www.python.jp/Zope/articles/tips/regex_howto/regex_howto_5#sec5-2

>>> p = re.compile('section{ ( [^}]* ) }', re.VERBOSE)
>>> p.sub(r'subsection{\1}','section{First} section{second}')
'subsection{First} subsection{second}'

この正規表現は何を表しているのか?re.VERBOSEは空白を無視する
まず'section{'ではじまり,文字列の先頭'^'か'}'の0回以上の繰り返しがあって,'}'で閉じるという風に読める.
しかし'{','}'に挟まれた文字列がグルーピングされて取り出されているのが理解できない.
p.subだとわかりにくいのでfindallで.

>>> p.findall('section{First} section{second}')
['First', 'second']

また'{','}'の間の文字列を取り出すなら

>>> p = re.compile('section{ ( [a-zA-Z]+? ) }', re.VERBOSE)
>>> p.findall('section{First} section{second}')
['First', 'second']

でいいと考えたのだけど.謎です.
後方参照という用語がすぐには理解できなかったがグループ化した表現を正規表現文字列の(まさにグループ化した)後で参照することみたいだ.変数を定義した後でないと参照できないのと似ている.