2007
Oct
27th
がわかっていなかったことがわかってなんだかがっくりきたという話。
ところがどっこいこれは間違いで、この結果は
aaa TARGET xxxだったり
aaa DUMMY bbb TARGET yyy xxxだったりすることがある文字列から TARGET を取り出したいというシチュエーションで、
re.compile('bbb (.*?) yyy|aaa (.*?) xxx')
を使っていました。対象としている文字列がどちらの場合でも、 "bbb (.*?) yyy" が先にマッチして TARGET が抜き出せると思っていたのです。ところがどっこいこれは間違いで、この結果は
>>> s = 'aaa DUMMY bbb TARGET yyy xxx'
>>> p = re.compile('bbb (.*?) yyy|aaa (.*?) xxx')
>>> p.search(s).groups()
(None, 'DUMMY bbb TARGET yyy')
となるのです。
kharakawa に相談したところ、正規表現オブジェクトが s を評価すると、まず aaa の部分がマッチしてそのまま評価を続け、 xxx まで進んで最終的に "aaa (.*?) xxx" にマッチするんだというようなことを教わりました。なので、例えば明示的に
>>> p = re.compile('bbb (.*?) yyy|aaa (?!bbb) (.*?) xxx')
とするのも手なのかもしれません。でもこれだと内包するようなケースが増えると書くのもしんどいし、後で見る人もしんどいので、
>>> pats = [re.compile('bbb (.*?) yyy'), re.compile('aaa (.*?) xxx')]
>>> for pat in pats:
... searched = pat.search(s)
... if searched:
... searched.groups()
... break
...
('TARGET',)
みたいにした方が良いかなと思いました。ちょっとあほっぽいような気もしなくもないけど。
Posted by setomits at 12:21 |
Comments: 0