2009-02-28 14 views
11

Il mio dilemma: sto passando alla mia funzione una stringa che mi serve per eseguire poi numerose manipolazioni di espressioni regolari. La logica è che se c'è una corrispondenza nella prima espressione regolare, fai una cosa. In caso contrario, controlla la corrispondenza con il secondo e fai qualcos'altro, se non controlla il terzo, e così via. Avrei potuto fare qualcosa di simile:Come concatenarsi in cascata tra più istruzioni regex in 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.] 

Tuttavia, questo si sente inutilmente prolisso, e di solito quando questo è il caso, significa che c'è un modo migliore che io sono uno che si affaccia o ancora non so.

Qualcuno ha un suggerimento per un modo migliore per farlo (meglio da un punto di vista dell'aspetto del codice, un punto di vista dell'utilizzo della memoria, o entrambi)?

+0

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

risposta

10

domanda simile dal torna a settembre: How do you translate this regular-expression idiom from Perl into Python?

Uso di variabili globali in un modulo forse non è il modo migliore per farlo, ma convertendolo in una 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

Grazie per il link! Non ho trovato questo argomento nella mia ricerca, ma è perfetto per quello che sto cercando di fare. Mi piace l'idea di usare una classe piuttosto che un modulo. –

1

Hmm ... si potrebbe usare qualcosa con la with costrutto ... 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

Sono le manipolazioni di ogni espressione regolare simile? Se è così, provate questo:

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

Sfortunatamente le manipolazioni variano a seconda della regex; a posteriori, avrei dovuto specificarlo nella domanda. –

0

Qui i vostri regexs e le partite non sono ripetute due volte:

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

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

In generale, in questo tipo di situazioni, si vuole fare il "data-driven" del codice. Cioè, metti le informazioni importanti in un contenitore e passa attraverso di esso.

Nel tuo caso, le informazioni importanti sono coppie (stringa, funzione).

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

Grazie per questo suggerimento! Questo era quello che probabilmente avrei finito per fare, ma la versione sovrascritta del modulo re è leggermente più adatta per questo progetto. –

2

ho avuto lo stesso problema del tuo. Here's la mia soluzione:

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 

E 'una soluzione leggermente modificata dalla risposta di Extracting info from large structured text files

+0

I dizionari non garantiscono l'ordinazione. Probabilmente dovresti usare una sequenza invece di un dict per ottenere un comportamento prevedibile. –

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) 

È possibile utilizzare questa classe in questo modo:

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' 
Problemi correlati