pattern - regex python search example




Alternativa a `match=re.match(); se partita:... 'idioma? (6)

Ecco la mia soluzione:

import re

s = 'hello world'

match = []
if match.append(re.match('w\w+', s)) or any(match):
    print('W:', match.pop().group(0))
elif match.append(re.match('h\w+', s)) or any(match):
    print('H:', match.pop().group(0))
else:
    print('No match found')

Puoi usare quante clausole elif se necessario.

Anche meglio:

import re

s = 'hello world'

if vars().update(match=re.match('w\w+', s)) or match:
    print('W:', match.group(0))
elif vars().update(match=re.match('h\w+', s)) or match:
    print('H:', match.group(0))
else:
    print('No match found')

Sia append e update restituiscono None . Quindi devi effettivamente controllare il risultato della tua espressione usando la parte o in ogni caso.

Sfortunatamente, questo funziona solo fino a quando il codice risiede al livello superiore, cioè non in una funzione.

https://code.i-harness.com

Se vuoi controllare se qualcosa corrisponde a un'espressione regolare, in tal caso, stampa il primo gruppo, lo fai ..

import re
match = re.match("(\d+)g", "123g")
if match is not None:
    print match.group(1)

Questo è completamente pedante, ma la variabile di match intermedia è un po 'fastidiosa ..

Lingue come Perl lo fanno creando nuove $1 .. $9 variabili per i gruppi di corrispondenza, come ..

if($blah ~= /(\d+)g/){
    print $1
}

Da questo commento reddit ,

with re_context.match('^blah', s) as match:
    if match:
        ...
    else:
        ...

..che pensavo fosse un'idea interessante, quindi ho scritto una semplice implementazione di questo:

#!/usr/bin/env python2.6
import re

class SRE_Match_Wrapper:
    def __init__(self, match):
        self.match = match

    def __exit__(self, type, value, tb):
        pass

    def __enter__(self):
        return self.match

    def __getattr__(self, name):
        if name == "__exit__":
            return self.__exit__
        elif name == "__enter__":
            return self.__name__
        else:
            return getattr(self.match, name)

def rematch(pattern, inp):
    matcher = re.compile(pattern)
    x = SRE_Match_Wrapper(matcher.match(inp))
    return x
    return match

if __name__ == '__main__':
    # Example:
    with rematch("(\d+)g", "123g") as m:
        if m:
            print(m.group(1))

    with rematch("(\d+)g", "123") as m:
        if m:
            print(m.group(1))

(Questa funzionalità potrebbe teoricamente essere applicata all'oggetto _sre.SRE_Match )

Sarebbe bello se si potesse saltare l'esecuzione del blocco di codice dell'istruzione with , se non ci fosse una corrispondenza, il che potrebbe semplificarlo.

with rematch("(\d+)g", "123") as m:
    print(m.group(1)) # only executed if the match occurred

..ma questo sembra impossibile sulla base di ciò che posso dedurre da PEP 343

Qualche idea? Come ho già detto, questo è davvero banale fastidio, quasi al punto di essere codice-golf ..


Ho un altro modo per farlo, basato sulla soluzione di Glen Maynard:

for match in [m for m in [re.match(pattern,key)] if m]:
    print "It matched: %s" % match

Simile alla soluzione di Glen, questo ittera 0 volte (se non corrisponde) o 1 (se corrisponde) volte.

Nessun sub necessario, ma meno ordinato di conseguenza.


Non credo che l'uso sia la soluzione in questo caso. Dovresti generare un'eccezione nella parte BLOCK (che è specificata dall'utente) e fare in modo che il metodo __exit__ restituisca True a "swallow" l'eccezione. Quindi non sembrerebbe mai bello.

Suggerirei di andare per una sintassi simile alla sintassi Perl. Crea il tuo modulo re esteso (lo chiamerò rex ) e fagli impostare le variabili nel suo spazio dei nomi del modulo:

if rex.match('(\d+)g', '123g'):
    print rex._1

Come puoi vedere nei commenti qui sotto, questo metodo non è né protetto dall'ambito né dal thread. Lo si userebbe solo se si fosse completamente certi che la propria applicazione non diventasse multi-thread in futuro e che tutte le funzioni chiamate dall'ambito in cui si sta utilizzando utilizzeranno lo stesso metodo.


Non penso sia banale. Non voglio dover cospargere un condizionale ridondante attorno al mio codice se sto scrivendo codice come quello spesso.

Questo è un po 'strano, ma puoi farlo con un iteratore:

import re

def rematch(pattern, inp):
    matcher = re.compile(pattern)
    matches = matcher.match(inp)
    if matches:
        yield matches

if __name__ == '__main__':
    for m in rematch("(\d+)g", "123g"):
        print(m.group(1))

La cosa strana è che sta usando un iteratore per qualcosa che non sta iterando - è più vicino a un condizionale, e a prima vista potrebbe sembrare che produrrà più risultati per ogni partita.

Sembra strano che un gestore di contesto non possa far saltare interamente la sua funzione gestita; mentre quello non è esplicitamente uno dei casi d'uso di "con", sembra un'estensione naturale.


Questo non è davvero carino, ma puoi approfittare della funzione getattr(object, name[, default]) usa in questo modo:

>>> getattr(re.match("(\d+)g", "123g"), 'group', lambda n:'')(1)
'123'
>>> getattr(re.match("(\d+)g", "X23g"), 'group', lambda n:'')(1)
''

Per simulare il flusso del gruppo di stampa if match , è possibile (ab) utilizzare l'istruzione for questo modo:

>>> for group in filter(None, [getattr(re.match("(\d+)g", "123g"), 'group', None)]):
        print(group(1))
123
>>> for group in filter(None, [getattr(re.match("(\d+)g", "X23g"), 'group', None)]):
        print(group(1))
>>> 

Ovviamente puoi definire una piccola funzione per fare il lavoro sporco:

>>> matchgroup = lambda p,s: filter(None, [getattr(re.match(p, s), 'group', None)])
>>> for group in matchgroup("(\d+)g", "123g"):
        print(group(1))
123
>>> for group in matchgroup("(\d+)g", "X23g"):
        print(group(1))
>>> 

Se stai facendo un sacco di questi in un posto, ecco una risposta alternativa:

import re
class Matcher(object):
    def __init__(self):
        self.matches = None
    def set(self, matches):
        self.matches = matches
    def __getattr__(self, name):
        return getattr(self.matches, name)

class re2(object):
    def __init__(self, expr):
        self.re = re.compile(expr)

    def match(self, matcher, s):
        matches = self.re.match(s)
        matcher.set(matches)
        return matches

pattern = re2("(\d+)g")
m = Matcher()
if pattern.match(m, "123g"):
    print(m.group(1))
if not pattern.match(m, "x123g"):
    print "no match"

È possibile compilare la regex una volta con lo stesso thread safe di re, creare un singolo oggetto Matcher riutilizzabile per l'intera funzione e quindi è possibile utilizzarlo in modo molto conciso. Questo ha anche il vantaggio di poterlo invertire in modo ovvio - per farlo con un iteratore, devi passare una bandiera per dire di invertire il risultato.

Non è di grande aiuto se stai facendo una sola partita per funzione, però; non vuoi mantenere gli oggetti Matcher in un contesto più ampio di quello; causerebbe gli stessi problemi della soluzione di Blixt.







idioms