2009-12-28 19 views
19

Ok, quindi questo è qualcosa di completamente stupido, ma è qualcosa che semplicemente non ho mai imparato a fare ed è una seccatura.Regex per tutte le stringhe che non contengono una stringa?

Come specificare una stringa che non contiene una sequenza di altri caratteri. Ad esempio voglio abbinare tutte le linee che non terminano in '.config'

Vorrei pensare che ho potuto solo fare

.*[^(\.config)]$ 

, ma questo non funziona (perché no?)

so che posso fare

.*[^\.][^c][^o][^n][^f][^i][^g]$ 

ma vi prego, vi prego, mi dica che c'è un modo migliore

+1

che motore regex stai usando? Possono molto supportati nelle funzionalità. Dovresti taggare la tua domanda con il motore che stai utilizzando. – Andrew

+1

perché non usare 'grep -v" \ .config "'? – Lazer

+6

@Lazer - perché non tutto nel mondo è un sistema * nix? –

risposta

40

È possibile utilizzare negative lookbehind, ad esempio:

.*(?<!\.config)$ 

Questo corrisponde a tutte le stringhe ad eccezione di quelli che terminano con ".config"

+0

Funziona ma. * (?! = \. Config) $ no - Ho pensato che le due sintassi fossero equivalenti. Qualche indizio? –

+2

Non sono equivalenti. (? Manu

+1

No, non lo sono. Il lookahead negativo è '(?! Matchthis)', e il tuo esempio non può funzionare perché stai guardando avanti in un momento in cui sei già alla fine della stringa ('$'). –

2

A meno che non "grep" ... dal momento che non stai utilizzando il risultato di una corrispondenza, perché non cercare le stringhe che terminano in .config e saltarle? In Python:

import re 
isConfig = re.compile('\.config$') 
# List lst is given 
filteredList = [f.strip() for f in lst if not isConfig.match(f.strip())] 

Sospetto che ciò funzioni più rapidamente di un re più complesso.

+1

A meno che non si stia facendo grepping, perché utilizzare regex del tutto? Python ha "in" per una ragione. Altre lingue sono sicuro che hanno soluzioni simili. –

+0

Sì, questo è quello che faccio ora, ma è meglio sapere come fare in entrambi i modi. Mi sono imbattuto in situazioni in cui questo ha imposto qualche sintassi imbarazzante. –

2

Utilizzando il costrutto [^], è stata creata una classe di caratteri negata, che corrisponde a tutti i caratteri eccetto quelli nominati. Ordine dei caratteri nella partita candidato non importa, quindi questo non riuscirà a qualsiasi stringa che ha uno qualsiasi dei [(\.config) (o [)gi.\onc(])

Usa lookahead negativo, (con regexs Perl) in questo modo: (?!\.config$). Questo corrisponderà a tutte le stringhe che non corrispondono al letterale ".config"

15

La tua domanda contiene due domande, quindi ecco alcune risposte.

linee partita che non lo fanno contengono una certa stringa (diciamo .config) a tutti:

^(?:(?!\.config).)*$\r?\n? 

linee partita che non lo fanno fine in una certa stringa:

^.*(?<!\.config)$\r?\n? 

e, come bonus: le linee di corrispondenza che non sono iniziano con con una determinata stringa:

^(?!\.config).*$\r?\n? 

(ogni volta inclusi caratteri di nuova riga, se presenti.

Oh, e per rispondere perché la tua versione non funziona: [^abc] significa "qualsiasi (1) carattere tranne a, b, o c".La vostra altra soluzione sarebbe anche fallire su test.hg (perché finisce anche nella lettera g - la tua regex guarda ogni carattere singolarmente invece che l'intera stringa .config Ecco perché è necessario lookaround per gestire questo

2

Come avete chiesto.. un "modo migliore":. vorrei provare un approccio di "filtraggio" penso che è abbastanza facile da leggere e da capire:

#!/usr/bin/perl 

while(<>) { 
    next if /\.config$/; # ignore the line if it ends with ".config" 
    print; 
} 

come potete vedere ho usato codice perl come esempio, ma penso. hai capito?

aggiunto: questo approccio potrebbe essere utilizzato anche per la catena su più modelli di filtro e rimane ancora buona leggibile e facile da capire,

next if /\.config$/; # ignore the line if it ends with ".config" 
    next if /\.ini$/; # ignore the line if it ends with ".ini" 
    next if /\.reg$/; # ignore the line if it ends with ".reg" 

    # now we have filtered out all the lines we want to skip 
    ... process only the lines we want to use ... 
0

ho usato Regexpal prima di trovare questa pagina e si avvicinò con la seguente soluzione quando volevo per verificare che una stringa non contenga un'estensione di file:

Ho utilizzato l'opzione di casella di controllo m in modo che potessi presentare molte righe e vedere quali di esse hanno o non corrispondono.

in modo da trovare una stringa che non contiene altro "^(.(?!" + espressione non si vuole + "))*$"

My article on the uses of this particular regex

Problemi correlati