在Python中扩展string.Template类以简化正则表达式
我非常喜欢Python,主要是因为它简单易用。不过,正则表达式让我对Python的热爱有些动摇。于是,我想扩展一下已经存在的string.Template类,这个类可以让我在字符串中设置变量,从而获取已有字符串的值。
我第一次尝试的结果还不错,但也有一些缺点:
import re
from string import Template
class TemplateX(Template):
def getvalues(self,Str):
regex = r""
skipnext = False
for i in self.template:
if skipnext == False:
if i != "$":
regex += i
else:
regex += r"(.+)"
skipnext = True
else:
skipnext = False
values = re.search(regex,Str).groups()
return values
temp = TemplateX(" Coords; $x;$y;$z;\n")
newstring = temp.substitute(x="1",y="2",z="3")
print newstring
values = temp.getvalues(newstring)
print values
newstring的输出是:" Coords; 1;2;3;\n"
values的输出是:("1","2","3")
为了这个更简单的方法,我愿意牺牲一些正则表达式的功能。我的问题是,如何能给getvalues增加一点功能,让TemplateX中的变量可以是多个字符(就像Template类和substitute方法那样)。也就是说,我希望这样也能正常工作:
temp = TemplateX(" Coords; $xvar;$yvar;$zvar;\n")
newstring = temp.substitute(xvar="1",yvar="2",zvar="3")
print newstring
values = temp.getvalues(newstring)
print values
temp2 = TemplateX(" FindThese: $gx = $gy - $gz")
values2 = temp2.getvalues(" FindThese: $10000 = $10 - $5x")
2 个回答
使用 UserString 作为一个超级类,具体可以参考这个链接:http://docs.python.org/library/userdict.html#module-UserString
你基本上是在尝试把一个模板变成一个可以读取这个模板的正则表达式,对吧?这并不总是能做到,比如说你有一个模板 "$x$y"
和一个字符串 "abc"
,你无法确定它是 ("ab", "c")
、("abc", "")
还是其他情况。而且这不仅仅是模板变量挨在一起的情况。
所以如果你想做这种事情,你必须知道你输入的字符串里有什么。也就是说,变量之间有一些字符,这些字符在变量本身中是不存在的(例如,变量都是数字,而模板中它们之间有分号)。如果你只是解析一些输入,自己写正则表达式可能会更安全。
话虽如此,你 可以 做类似这样的事情:
class TemplateX(Template):
def getvalues(self,Str):
""" Reads a string matching the template to find the original values.
>>> temp = TemplateX("Blah: $xx;$y;")
>>> newsting = temp.substitute(xx="1",y="2")
>>> temp.getvalues(newstring)
('1', '2')
"""
regex = re.sub(self.pattern, "(.*)", self.template)
m = re.match(regex, Str)
return m.groups()
它使用模板自己的机制来找到占位符,并用正则表达式的通配符替换它们。然后它会在给定的字符串上运行这个正则表达式。
你也可以尝试获取最初的关键字参数:
def getvalues(self,Str):
regex = re.sub(self.pattern, r"(?P<\2>.*)", self.template)
m = re.match(regex, Str)
return m.groupdict()
然后用以下内容来处理:
temp = TemplateX("$a$a")
newstring = temp.substitute(a='a')
print temp.getvalues(newstring)