2010-09-08 62 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]),我們將不知道如何格式化這些字符。