2010-03-31 8 views
33

C'è un modo in Python per accedere ai gruppi di fiammiferi senza creare esplicitamente un oggetto di corrispondenza (o un altro modo per abbellire l'esempio di seguito)?Gruppi di corrispondenze in Python

Ecco un esempio per chiarire la mia motivazione per la domanda:

Seguendo codice Perl

if ($statement =~ /I love (\w+)/) { 
    print "He loves $1\n"; 
} 
elsif ($statement =~ /Ich liebe (\w+)/) { 
    print "Er liebt $1\n"; 
} 
elsif ($statement =~ /Je t\'aime (\w+)/) { 
    print "Il aime $1\n"; 
} 

tradotto in Python

m = re.search("I love (\w+)", statement) 
if m: 
    print "He loves",m.group(1) 
else: 
    m = re.search("Ich liebe (\w+)", statement) 
    if m: 
    print "Er liebt",m.group(1) 
    else: 
    m = re.search("Je t'aime (\w+)", statement) 
    if m: 
     print "Il aime",m.group(1) 

sembra molto scomodo (if-else-cascade, combina creazione di oggetti).

+0

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

+0

Avvertenza: Python re.match() corrisponde specificamente all'inizio del target. Quindi re.match ("I love (\ w +)", "Oh! How I love you") NON corrisponde. O vuoi usare re.search() o prefisso esplicitamente la regex con i modelli jolly appropriati per re.match (". * I love (\ w +)", ...) –

+0

@Jim Dennis: grazie a precisare; Ho adattato l'esempio python di conseguenza – Curd

risposta

31

Si potrebbe creare un po 'di classe che restituisce il risultato booleano di chiamare partita, e conserva i gruppi abbinati per il successivo recupero:

import re 

class REMatcher(object): 
    def __init__(self, matchstring): 
     self.matchstring = matchstring 

    def match(self,regexp): 
     self.rematch = re.match(regexp, self.matchstring) 
     return bool(self.rematch) 

    def group(self,i): 
     return self.rematch.group(i) 


for statement in ("I love Mary", 
        "Ich liebe Margot", 
        "Je t'aime Marie", 
        "Te amo Maria"): 

    m = REMatcher(statement) 

    if m.match(r"I love (\w+)"): 
     print "He loves",m.group(1) 

    elif m.match(r"Ich liebe (\w+)"): 
     print "Er liebt",m.group(1) 

    elif m.match(r"Je t'aime (\w+)"): 
     print "Il aime",m.group(1) 

    else: 
     print "???" 
+0

+1 bella soluzione; anche se un po 'prolisso – Curd

+1

Potrebbe essere prolisso, ma inserirai la classe REMatcher in un bel modulo che dovrai importare quando necessario. Non faresti questa domanda per un problema che non si presenterà più in futuro, vero? – tzot

+1

@ ΤΖΩΤΖΙΟΥ: Sono d'accordo; ma, perché non è ancora una classe del genere in re? – Curd

13

meno efficiente, ma più semplice di aspetto:

m0 = re.match("I love (\w+)", statement) 
m1 = re.match("Ich liebe (\w+)", statement) 
m2 = re.match("Je t'aime (\w+)", statement) 
if m0: 
    print "He loves",m0.group(1) 
elif m1: 
    print "Er liebt",m1.group(1) 
elif m2: 
    print "Il aime",m2.group(1) 

Il problema con la roba Perl è l'aggiornamento implicita di qualche variabile nascosta. È semplicemente difficile da ottenere in Python perché è necessario avere un'istruzione di assegnazione per aggiornare effettivamente qualsiasi variabile.

La versione con meno ripetizioni (e migliore efficienza) è questo:

pats = [ 
    ("I love (\w+)", "He Loves {0}"), 
    ("Ich liebe (\w+)", "Er Liebe {0}"), 
    ("Je t'aime (\w+)", "Il aime {0}") 
] 
for p1, p3 in pats: 
    m= re.match(p1, statement) 
    if m: 
     print p3.format(m.group(1)) 
     break 

una variazione minore che alcune persone Perl preferiscono:

pats = { 
    "I love (\w+)" : "He Loves {0}", 
    "Ich liebe (\w+)" : "Er Liebe {0}", 
    "Je t'aime (\w+)" : "Il aime {0}", 
} 
for p1 in pats: 
    m= re.match(p1, statement) 
    if m: 
     print pats[p1].format(m.group(1)) 
     break 

Questo non è certo degno di nota, tranne che viene in su a volte dai programmatori Perl.

+3

@ S.Lott: ok, la tua soluzione evita l'if-else-cascade, ma a spese di fare match non necessari (m1 e m2 non sono necessari se m0 corrisponde); ecco perché non sono veramente soddisfatto di questa soluzione. – Curd

+2

+1 Mi piace la seconda versione migliore ... – Curd

+0

+1 per la seconda via –

3

questa non è una soluzione regolare.

alist={"I love ":""He loves"","Je t'aime ":"Il aime","Ich liebe ":"Er liebt"} 
for k in alist.keys(): 
    if k in statement: 
     print alist[k],statement.split(k)[1:] 
1

Si potrebbe creare una funzione di supporto:

def re_match_group(pattern, str, out_groups): 
    del out_groups[:] 
    result = re.match(pattern, str) 
    if result: 
     out_groups[:len(result.groups())] = result.groups() 
    return result 

E poi usare in questo modo:

groups = [] 
if re_match_group("I love (\w+)", statement, groups): 
    print "He loves", groups[0] 
elif re_match_group("Ich liebe (\w+)", statement, groups): 
    print "Er liebt", groups[0] 
elif re_match_group("Je t'aime (\w+)", statement, groups): 
    print "Il aime", groups[0] 

E 'un po' goffo, ma ottiene il lavoro fatto.

Problemi correlati