2009-06-02 16 views
49

Ho un motore di template Python che usa pesantemente regexp. Esso utilizza la concatenazione come:Sintassi di espressioni regolari per "corrispondenza nulla"?

re.compile(regexp1 + "|" + regexp2 + "*|" + regexp3 + "+") 

posso modificare le singole stringhe (RegExp1, regexp2 ecc).

Esiste un'espressione piccola e leggera che non corrisponde a nulla, che posso utilizzare all'interno di un modello in cui non voglio corrispondenze? Sfortunatamente, a volte '+' o '*' vengono aggiunti all'atrio regexp, quindi non posso usare la stringa vuota - un errore "nulla da ripetere" aumenterà.

+1

http://stackoverflow.com/questions/1723182/a-regex-that-will-never-be-matched-by-anything –

risposta

76

Questo non deve corrispondere nulla:

re.compile('$^') 

Quindi, se si sostituisce RegExp1, regexp2 e regexp3 con '$ ^' sarà impossibile trovare una corrispondenza. A meno che non si stia utilizzando la modalità multi linea.


Dopo alcuni test ho trovato una soluzione migliore

re.compile('a^') 

E 'impossibile da abbinare e fallirà prima rispetto alla soluzione precedente. È possibile sostituire un qualsiasi altro carattere e sarà sempre impossibile eguagliare

+0

Ciò non corrisponde a nulla di sicuro ed è leggero per il motore regexp da elaborare? (non voglio che il mio stub regexps per mangiare un sacco di CPU) – grigoryvp

+0

@Eye of hell. Dovrebbe essere leggero. Questo cercherà di abbinare un fine linea seguito da un inizio linea. Quale è impossibile in una riga. –

+1

Ma possibile con più linee ovviamente (a seconda se il flag è abilitato) - per una soluzione che funziona indipendentemente dal fatto che il flag sia abilitato, vedere la mia risposta. –

2

Forse '.{0}'?

+0

Restituisce un oggetto match – grigoryvp

3
"()" 

corrisponde a niente e niente solo.

+0

Ciò corrisponderà a una stringa vuota. Dipende da ciò che @Eye of Hell sta richiedendo. Se non vuole assolutamente niente, allora non funzionerà. –

+3

No: questo corrisponde a qualsiasi cosa, ma è considerato uno schema errato in molte implementazioni di espressioni regolari (a volte dipende dalle bandiere) – ShuggyCoUk

+0

Non si vuole eguagliare nulla. Controllerò come interpreta python "()". – grigoryvp

15

per abbinare una stringa vuota - anche in modalità multilinea - è possibile utilizzare \A\Z, quindi:

re.compile('\A\Z|\A\Z*|\A\Z+') 

La differenza è che \A e \Z sono inizio e fine stringa, mentre ^ e $ questi può corrispondere all'inizio/fine di righe, quindi $^|$^*|$^+ potrebbe potenzialmente corrispondere a una stringa contenente newline (se il flag è abilitato).

E per riuscire a soddisfare qualsiasi cosa (anche una stringa vuota), semplicemente tentare di trovare i contenuti prima dell'inizio della stringa, ad esempio:

re.compile('.\A|.\A*|.\A+') 

Poiché non i personaggi possono venire prima \ A (per definizione) , questo fallirà sempre.

+0

Il tuo aspetto è più bello del mio dal momento che presumo che uscirebbe più velocemente rispetto all'utilizzo di fine linea. – ShuggyCoUk

+0

Peter, tu usi \ z (minuscolo) mentre la mia guida tascabile Python mi dice che l'asserzione di fine stringa è \ Z (maiuscolo) ?! – ThomasH

+0

ThomasH, entrambi sono di fine stringa, ma la versione maiuscola consente una nuova riga finale mentre quella minuscola no. –

1

Potreste usare
\z..
Questa è la fine assoluta della stringa, seguita da due di nulla

Se + o * è appiccicato alla fine questo funziona ancora rifiuta di corrispondere nulla

0

Or , usa un po 'di list comprehension per rimuovere le voci di regexp inutili e unisciti per metterle tutte insieme.Qualcosa di simile:

re.compile('|'.join([x for x in [regexp1, regexp2, ...] if x != None])) 

Assicurarsi di aggiungere alcuni commenti accanto a quella linea di codice se :-)

23

(?!) dovrebbe sempre non riescono a corrispondere. È la previsione negativa della larghezza zero. Se ciò che è nelle parentesi corrisponde allora l'intera corrispondenza fallisce. Dato che non ha nulla in esso, fallirà la partita per qualsiasi cosa (incluso niente).

+3

Esatto, stavo proprio per postare anche questo: questo è il modo migliore, se la tua lingua supporta i lookaheads. (? =) corrisponde a ogni stringa. –

Problemi correlati