2009-02-28 6 views
11

Mon dilemme: Je transmets à ma fonction une chaîne dont j'ai besoin pour effectuer de nombreuses manipulations regex. La logique est que s'il y a une correspondance dans la première regex, faites une chose. S'il n'y a pas de correspondance, recherchez une correspondance avec la seconde et faites autre chose, sinon vérifiez la troisième, et ainsi de suite. Je pouvais faire quelque chose comme ceci:Comment concilier de façon concise plusieurs instructions regex en Python

if re.match('regex1', string): 
    match = re.match('regex1', string) 
    # Manipulate match.group(n) and return 
elif re.match('regex2', string): 
    match = re.match('regex2', string) 
    # Do second manipulation 
[etc.] 

Cependant, cela se sent inutilement bavard, et généralement quand c'est le cas, cela signifie qu'il ya une meilleure façon que je suis soit avec vue ou ne sais pas encore.

Quelqu'un a-t-il une suggestion pour une meilleure façon de faire cela (mieux du point de vue de l'aspect du code, du point de vue de l'utilisation de la mémoire, ou les deux)?

+0

Dupicate: http://stackoverflow.com/questions/122277/how-do-you-translate-this-regular-expression-idiom-from-perl-into-python –

Répondre

10

question similaire de retour en septembre: How do you translate this regular-expression idiom from Perl into Python?

Utilisation des variables globales dans un module peut-être pas la meilleure façon de le faire, mais la transformer en une classe:

import re 

class Re(object): 
    def __init__(self): 
    self.last_match = None 
    def match(self,pattern,text): 
    self.last_match = re.match(pattern,text) 
    return self.last_match 
    def search(self,pattern,text): 
    self.last_match = re.search(pattern,text) 
    return self.last_match 

gre = Re() 
if gre.match(r'foo',text): 
    # do something with gre.last_match 
elif gre.match(r'bar',text): 
    # do something with gre.last_match 
else: 
    # do something else 
+0

Merci pour le lien! Je n'ai pas trouvé ce sujet dans ma recherche, mais c'est pour ce que j'essaie de faire. J'aime l'idée d'utiliser une classe plutôt qu'un module, aussi. –

1

Hmm ... vous pouvez utiliser quelque chose avec le with construction ... um

class rewrapper() 
    def __init__(self, pattern, target): 
     something 

    def __enter__(self): 
     something 

    def __exit__(self): 
     something 


with rewrapper("regex1", string) as match: 
    etc 

with rewrapper("regex2", string) as match: 
    and so forth 
0

Les manipulations pour chaque regex similaire? Si oui, essayez ceci:

for regex in ('regex1', 'regex2', 'regex3', 'regex4'): 
    match = re.match(regex, string) 
    if match: 
     # Manipulate match.group(n) 
     return result 
+0

Malheureusement, les manipulations varient pour les différentes regex; rétrospectivement, j'aurais dû préciser cela dans la question. –

0

Ici vos regexs et les matches ne sont pas répétées deux fois:

match = re.match('regex1', string) 
if match: 
    # do stuff 
    return 

match = re.match('regex2', string) 
if match: 
    # do stuff 
    return 
24

D'une manière générale, dans ce genre de situations, vous voulez faire le code "data driven". C'est-à-dire, mettez les informations importantes dans un conteneur, et bouclez-le.

Dans votre cas, les informations importantes sont des paires (chaîne, fonction).

import re 

def fun1(): 
    print('fun1') 

def fun2(): 
    print('fun2') 

def fun3(): 
    print('fun3') 

regex_handlers = [ 
    (r'regex1', fun1), 
    (r'regex2', fun2), 
    (r'regex3', fun3) 
    ] 

def example(string): 
    for regex, fun in regex_handlers: 
     if re.match(regex, string): 
      fun() # call the function 
      break 

example('regex2') 
+0

Merci pour cette suggestion! C'est ce que j'allais probablement faire, mais la version surchargée du module re est un peu mieux adapté à ce projet. –

2

j'avais le même problème que le vôtre. Here's ma solution:

import re 

regexp = { 
    'key1': re.compile(r'regexp1'), 
    'key2': re.compile(r'regexp2'), 
    'key3': re.compile(r'regexp3'), 
    # ... 
} 

def test_all_regexp(string): 
    for key, pattern in regexp.items(): 
     m = pattern.match(string) 
     if m: 
      # do what you want 
      break 

C'est un solution légèrement modifiée de la réponse de Extracting info from large structured text files

+0

Les dictionnaires ne garantissent pas la commande. Vous devriez probablement utiliser une séquence au lieu d'une dict pour obtenir un comportement prévisible. –

0
class RegexStore(object): 
    _searches = None 

    def __init__(self, pat_list): 
     # build RegEx searches 
     self._searches = [(name,re.compile(pat, re.VERBOSE)) for 
         name,pat in pat_list] 

    def match(self, text): 
     match_all = ((x,y.match(text)) for x,y in self._searches) 
     try: 
     return ifilter(op.itemgetter(1), match_all).next() 
     except StopIteration, e: 
     # instead of 'name', in first arg, return bad 'text' line 
     return (text,None) 

Vous pouvez utiliser cette classe comme ceci:

rs = RegexStore((('pat1', r'.*STRING1.*'), 
        ('pat2', r'.*STRING2.*'))) 
name,match = rs.match("MY SAMPLE STRING1") 

if name == 'pat1': 
    print 'found pat1' 
elif name == 'pat2': 
    print 'found pat2' 
Questions connexes