2010-09-08 50 views
3

我的想法是使用正则表达式模式作为模板,并想知道在Python(3或更新版本)中是否有方便的方法。在Python中使用正则表达式作为模板

import re 

pattern = re.compile("/something/(?P<id>.*)") 
pattern.populate(id=1) # that is what I'm looking for 

应导致

/something/1 
+0

这不是真正的正则表达式。 SilentGhost的例子就是你要找的。 – Falmarri 2010-09-09 04:52:10

+0

是的,我知道这不是什么正则表达式,但我可以使用正则表达式进行匹配并作为我的案例的模板。 – deamon 2010-09-10 11:09:44

+0

这对构建像'{%url%}'标签中的Django类似的网址很有用。 – lig 2011-12-14 12:32:22

回答

3

,这不是什么正则表达式,你可以只使用普通的字符串格式。

>>> '/something/{id}'.format(id=1) 
'/something/1' 
+1

为什么要投票?这个答案对我来说是正确的 – 2010-09-08 23:05:00

1

保存编译直至置换后:

pattern = re.compile("/something/(?P<%s>.*)" % 1) 
1

下面是我创建了一个轻量类做了你在找什么。您可以编写单个正则表达式,并使用该表达式对这两个匹配字符串并生成字符串。

代码底部有一个关于如何使用它的小例子。

一般情况下,您通常会构造一个正则表达式,并且正常使用matchsearch函数。 format函数的用法与string.format很相似,用于生成一个新的字符串。

import re 
regex_type = type(re.compile("")) 

# This is not perfect. It breaks if there is a parenthesis in the regex. 
re_term = re.compile(r"(?<!\\)\(\?P\<(?P<name>[\w_\d]+)\>(?P<regex>[^\)]*)\)") 

class BadFormatException(Exception): 
    pass 

class RegexTemplate(object): 
    def __init__(self, r, *args, **kwargs): 
     self.r = re.compile(r, *args, **kwargs) 

    def __repr__(self): 
     return "<RegexTemplate '%s'>"%self.r.pattern 

    def match(self, *args, **kwargs): 
     '''The regex match function''' 
     return self.r.match(*args, **kwargs) 

    def search(self, *args, **kwargs): 
     '''The regex match function''' 
     return self.r.search(*args, **kwargs) 

    def format(self, **kwargs): 
     '''Format this regular expression in a similar way as string.format. 
     Only supports true keyword replacement, not group replacement.''' 
     pattern = self.r.pattern 
     def replace(m): 
      name = m.group('name') 
      reg = m.group('regex') 
      val = kwargs[name] 
      if not re.match(reg, val): 
       raise BadFormatException("Template variable '%s' has a value " 
        "of %s, does not match regex %s."%(name, val, reg)) 
      return val 

     # The regex sub function does most of the work 
     value = re_term.sub(replace, pattern) 

     # Now we have un-escape the special characters. 
     return re.sub(r"\\([.\(\)\[\]])", r"\1", value) 

def compile(*args, **kwargs): 
    return RegexTemplate(*args, **kwargs) 

if __name__ == '__main__': 
    # Construct a typical URL routing regular expression 
    r = RegexTemplate(r"http://example\.com/(?P<year>\d\d\d\d)/(?P<title>\w+)") 
    print r 

    # This should match 
    print r.match("http://example.com/2015/article") 
    # Generate the same URL using url formatting. 
    print r.format(year = "2015", title = "article") 

    # This should not match 
    print r.match("http://example.com/abcd/article") 
    # This will raise an exception because year is not formatted properly 
    try: 
     print r.format(year = "15", title = "article") 
    except BadFormatException as e: 
     print e 

有一些限制:

  • 格式功能只与关键字参数工作(你不能使用\1样式格式为string.format)。
  • 还有一个元素与子元素匹配的错误,例如RegexTemplate(r'(?P<foo>biz(baz)?)')。这可以通过一些工作来纠正。
  • 如果您的正则表达式包含命名组以外的字符类(例如,[a-z123]),我们将不知道如何格式化这些字符。