Regex per stringa che non termina con il suffisso specificato


190

Non sono stato in grado di trovare una regex adeguata per abbinare qualsiasi stringa che non termina con una condizione. Ad esempio, non voglio abbinare nulla che termina con un a.

Questo corrisponde

b
ab
1

Questo non corrisponde

a
ba

So che la regex dovrebbe terminare $per segnare la fine, anche se non so cosa dovrebbe precederla.

Modifica : la domanda originale non sembra essere un esempio legittimo per il mio caso. Quindi: come gestire più di un personaggio? Di 'qualcosa che non finisce con ab?

Sono stato in grado di risolvere questo problema, usando questo thread :

.*(?:(?!ab).).$

Sebbene l'aspetto negativo di questo sia, non corrisponde a una stringa di un personaggio.


5
Questo non è un duplicato della domanda collegata: la corrispondenza solo con la fine richiede una sintassi diversa rispetto alla corrispondenza in qualsiasi punto all'interno di una stringa. Guarda qui la risposta migliore.
Jaustin,

Sono d'accordo, questo non è un duplicato della domanda collegata. Mi chiedo come possiamo rimuovere i "segni" sopra?
Alan Cabrera,

Non esiste un collegamento del genere che posso vedere.
Alan Cabrera,

Risposte:


252

Non ci dai la lingua, ma se il tuo supporto al sapore regex guarda dietro l'asserzione , questo è quello che ti serve:

.*(?<!a)$

(?<!a)è un'asserzione negata che assicura che, prima della fine della stringa (o riga con mmodificatore), non ci sia il carattere "a".

Guardalo qui in RegExr

Puoi anche estenderlo facilmente con altri caratteri, poiché controlla la stringa e non è una classe di caratteri.

.*(?<!ab)$

Questo corrisponderebbe a tutto ciò che non termina con "ab", vederlo su Regexr


1
Non conosco RegexPAL, ma le regex sono diverse in tutte le lingue e le asserzioni dietro le spalle sono una funzionalità avanzata che non è supportata da tutti.
Stema,

7
regexpal è un tester regex basato su javascript e javascript non supporta asserzioni lookbehind che sono tristi
HamZa,

Lookbehinds non sono supportati su regexr (javascript)
Stealth Rabbi

1
La mancanza di lookbehind in JS mi fa piangere. Se stai facendo sul lato server anche se probabilmente puoi usare il modulo PCRE su NPM o simile per usarli direttamente (è un insieme di collegamenti quindi non penso che tu possa usarlo front-end)
Eirik Birkeland

Altri tipi di lookahead / lookbehind asserzioni: stackoverflow.com/q/2973436/12484
John Schneider

76

Usa il simbolo not ( ^):

.*[^a]$

Se metti il ^simbolo all'inizio delle parentesi, significa "tutto tranne le cose tra parentesi". $è semplicemente un'ancora fino alla fine.

Per più personaggi , inseriscili tutti nel loro set di caratteri:

.*[^a][^b]$

1
+1, con l'avvertenza che questo non corrisponde alla stringa vuota (che può essere o non essere come previsto), quindi il significato è piuttosto "qualsiasi carattere che non è tra parentesi".
Fred Foo,

3
@ 0A0D: una stringa contenente spazi bianchi non è una stringa vuota.
Fred Foo,

7
@ 0A0D In realtà, non è un dibattito, è un dato di fatto
tckmn

8
@Doorknob: che non corrisponde aeo cb.
Fred Foo,

1
No, neanche questo consentirebbe "acb".
Menno,

49

Per cercare i file che non terminano con ".tmp", utilizziamo la seguente regex:

^(?!.*[.]tmp$).*$

Testato con il Regex Tester fornisce i seguenti risultati:

inserisci qui la descrizione dell'immagine


1
Questo è interessante, ^.*(?![.]tmp$)hai idea del perché funzioni e perché no?
Łukasz Zaroda,

4
Il tuo inizio .*corrisponde già all'intera stringa, quindi l'esclusione rimanente non funziona più.
Cinque

Per i miei scopi, ha funzionato e le altre risposte no. Grazie!
David Moritz,

8
.*[^a]$

la regex sopra corrisponderà a stringhe che non terminano a.


Ho esteso la mia domanda poiché l'esempio originale non sembra corrispondere completamente al mio caso. Puoi risolverlo?
Menno,

5

Prova questo

/.*[^a]$/

Il []denota una classe di caratteri, e le ^inverte la classe di caratteri per abbinare tutto, ma una a.


1

La domanda è vecchia ma non sono riuscito a trovare una soluzione migliore che inserisco la mia qui. Trova tutte le unità USB ma non elenca le partizioni , rimuovendo così la "parte [0-9]" dai risultati. Ho finito per fare due grep, l'ultimo nega il risultato:

ls -1 /dev/disk/by-path/* | grep -P "\-usb\-" | grep -vE "part[0-9]*$"

Questo risulta sul mio sistema:

pci-0000:00:0b.0-usb-0:1:1.0-scsi-0:0:0:0

Se solo volessi le partizioni potrei fare:

ls -1 /dev/disk/by-path/* | grep -P "\-usb\-" | grep -E "part[0-9]*$"

Dove ottengo:

pci-0000:00:0b.0-usb-0:1:1.0-scsi-0:0:0:0-part1
pci-0000:00:0b.0-usb-0:1:1.0-scsi-0:0:0:0-part2

E quando lo faccio:

readlink -f /dev/disk/by-path/pci-0000:00:0b.0-usb-0:1:1.0-scsi-0:0:0:0

Ottengo:

/dev/sdb

1

La risposta accettata va bene se è possibile utilizzare le soluzioni alternative. Tuttavia, esiste anche un altro approccio per risolvere questo problema.

Se guardiamo la regex ampiamente proposta per questa domanda:

.*[^a]$

Scopriremo che funziona quasi . Non accetta una stringa vuota, che potrebbe essere un po 'inconsistente. Tuttavia, questo è un problema minore quando si ha a che fare con un solo personaggio. Tuttavia, se vogliamo escludere l'intera stringa, ad esempio "abc", allora:

.*[^a][^b][^c]$

non lo farà. Non accetterà ac, per esempio.

Tuttavia, esiste una soluzione semplice per questo problema. Possiamo semplicemente dire:

.{,2}$|.*[^a][^b][^c]$

o versione più generalizzata:

.{,n-1}$|.*[^firstchar][^secondchar]$ dove n è la lunghezza della stringa che vuoi vietare (perché abcè 3), e firstchar, secondchar... sono il primo, il secondo ... ennesimo carattere della stringa (poiché abcsarebbe a, quindi b, quindi c).

Ciò deriva da una semplice osservazione che una stringa più corta del testo che non vieteremo non può contenere questo testo per definizione. Quindi possiamo accettare tutto ciò che è più breve ("ab" non è "abc"), o qualcosa di abbastanza lungo da accettare, ma senza la fine.

Ecco un esempio di find che eliminerà tutti i file che non sono .jpg:

find . -regex '.{,3}$|.*[^.][^j][^p][^g]$' -delete


.{,2}$|.*[^a][^b][^c]$non corrispondeccc
psalaets

0

Tutto ciò che corrisponde a qualcosa che termina con un --- .*a$Quindi quando abbini la regex, annulla la condizione o in alternativa puoi anche fare .*[^a]$dove [^a]significa tutto ciò che ènot a


0

Se si sta utilizzando grepo sedla sintassi sarà leggermente diversa. Si noti che il [^a][^b]metodo sequenziale non funziona qui:

balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n'
jd8a
8$fb
q(c
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^a]$"
8$fb
q(c
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^b]$"
jd8a
q(c
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^c]$"
jd8a
8$fb
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^a][^b]$"
jd8a
q(c
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^a][^c]$"
jd8a
8$fb
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^a^b]$"
q(c
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^a^c]$"
8$fb
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^b^c]$"
jd8a
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^b^c^a]$"

FWIW, sto trovando gli stessi risultati in Regex101 , che penso sia la sintassi JavaScript.

Cattivo: https://regex101.com/r/MJGAmX/2
Buono: https://regex101.com/r/LzrIBu/2

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.