2010-09-08 6 views
3

J'ai l'idée d'utiliser un modèle regex comme modèle et je me demande s'il existe un moyen pratique de le faire en Python (3 ou plus récent).Utilisation d'une regex en tant que modèle avec Python

import re 

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

devrait aboutir à

/something/1 
+0

Ce n'est pas vraiment ce qu'est une regex. L'exemple de SilentGhost est ce que vous cherchez. – Falmarri

+0

Oui, je sais que ce n'est pas ce que les regex ont été faites, mais je pourrais utiliser une regex pour faire correspondre et comme modèle dans mon cas. – deamon

+0

Il est utile pour construire des URLs comme Django dans la balise '{% url%}'. – lig

Répondre

3

ce n'est pas ce que sont pour regex, vous pouvez simplement utiliser la mise en forme de chaîne normale.

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

Pourquoi le vote négatif? Cette réponse me semble correcte –

1

Save the compilation qu'après la substitution:

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

Voici une classe de poids léger, je crée qui fait ce que vous cherchez. Vous pouvez écrire une seule expression régulière et utiliser cette expression pour les deux chaînes correspondantes et générer des chaînes.

Il y a un petit exemple en bas du code sur la façon de l'utiliser.

Généralement, vous construisez normalement une expression régulière et utilisez les fonctions match et search comme d'habitude. La fonction format est utilisée un peu comme string.format pour générer une nouvelle chaîne.

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 

Il existe des limites:

  • La fonction de format ne fonctionne qu'avec des arguments de mots-clés (vous ne pouvez pas utiliser la mise en forme de style \1 comme dans string.format). Il existe également un bogue avec des éléments correspondants avec des sous-éléments, par exemple RegexTemplate(r'(?P<foo>biz(baz)?)'). Cela pourrait être corrigé avec un peu de travail.
  • Si votre expression régulière contient des classes de caractères en dehors d'un groupe nommé (par exemple, [a-z123]), nous ne saurons pas comment les formater.
Questions connexes