u"""
str.format用の文字列から、format後の文字列にマッチする正規表現を作ります。
仕様:末尾まで完全に一致させます。
format後の文字列の末尾に余計な物がついていると、マッチしません。
仕様:str.formatのパラメータには数値のみが渡されると想定します。
"{0}".format(None) のように、数値以外のものを渡す場合は使えません。
>>> fmt = "PaletteItem({image_id}, QColor({red}, {green}, {blue}), {index})"
>>> s = fmt.format(image_id=0, red=1,green=2, blue=3, index=4)
>>> m = match(fmt, s)
>>> m.group("red")
'1'
>>> matchdict(fmt, s)
{'blue': 3, 'image_id': 0, 'green': 2, 'red': 1, 'index': 4}
>>> matchdict(fmt, s + "some noise in tail") is None
True
>>> match(fmt, s + "some noise in tail") is None
True
"""
from __future__ import division, print_function
__metaclass__ = type
import re
import string
def escape(pattern):
s = list(pattern)
not_escape = set(string.digits + string.ascii_letters + " " + "_")
for i, c in enumerate(pattern):
if c not in not_escape:
if c == "\000":
s[i] = "\\000"
else:
s[i] = "\\" + c
return pattern[:0].join(s)
def format_to_re(format_string):
ss = escape(format_string)
ss = ss.replace(" ", "\\s*")
def repl(m):
if m.group("double"):
return "\\" + m.group("double")[0]
else:
return r"(?P<{0}>(\+|\-)?\d+)".format(m.group("field"))
pattern = r"\\{(?P<field>.+?)\\}|(?P<double>\\{\\{|\\}\\})"
return re.sub(pattern, repl, ss) + r"\s*$"
def match(format, ss):
return re.match(format_to_re(format), ss)
def matchdict(format, ss):
m = match(format, ss)
if not m:
return None
else:
return dict((k, int(v)) for k, v in m.groupdict().items())
def main():
import doctest
doctest.testmod()
if "__main__" == __name__:
main()