Regex: come abbinare tutto tranne uno schema particolare


Risposte:


192

È possibile utilizzare un'asserzione anticipata:

(?!999)\d{3}

Questo esempio corrisponde a tre cifre diverse da 999.


Ma se ti capita di non avere un'implementazione di espressioni regolari con questa funzione (vedi Confronto dei sapori di espressioni regolari ), probabilmente devi creare un'espressione regolare con le funzionalità di base da solo.

Un'espressione regolare compatibile solo con la sintassi di base sarebbe:

[0-8]\d\d|\d[0-8]\d|\d\d[0-8]

Questo corrisponde anche a qualsiasi sequenza di tre cifre che non lo è 999.


1
Look-ahead non è una sintassi delle espressioni regolari standard, è un'estensione Perl, funzionerà solo in Perl, PCRE (Regl compatibile Perl) o altre implementazioni non standard
Juliano

10
Potrebbe non essere standard, ma la maggior parte delle lingue moderne non lo supporta? Che lingua non supporta le previsioni al giorno d'oggi?
Bryan Oakley,

1
È vero. Ma la maggior parte degli aromi regex supportano questa funzione (vedere < regular-expressions.info/refflavors.html> ).
Gumbo,

1
penso che anche l'ultimo regex non corrisponderebbe a 009, 019 ... ecc.
Sebastian Viereck,

1
Lo standard Lex per C non utilizza PCRE :-(
pieman72

30

Se si desidera abbinare una parola A in una stringa e non corrispondere a una parola B. Ad esempio: Se si dispone di un testo:

1. I have a two pets - dog and a cat
2. I have a pet - dog

Se vuoi cercare righe di testo che hanno un cane per un animale domestico e NON ha un gatto , puoi usare questa espressione regolare:

^(?=.*?\bdog\b)((?!cat).)*$

Troverà solo la seconda riga:

2. I have a pet - dog

Non è riuscito a menzionarlo nella domanda, ma l'OP sta effettivamente utilizzando il findstrcomando DOS . Offre solo un piccolo sottoinsieme delle funzionalità che ci si aspetta di trovare in uno strumento regex; lookahead non è tra questi. (Ho appena aggiunto il tag findstr da solo.)
Alan Moore,

2
hm, si, l'ho trovato ora in uno dei suoi commenti sui post. Ho visto Regex nel titolo. Ad ogni modo, se qualcuno trova questo post durante la ricerca dello stesso per un'espressione regolare, come ho fatto io, forse potrebbe essere utile a qualcuno :) grazie per i commenti
Aleks

15

Abbina il pattern e usa la lingua host per invertire il risultato booleano della corrispondenza. Questo sarà molto più leggibile e mantenibile.


1
Quindi finisco con (~ A o B) anziché (A e ~ B). Non risolve il mio problema.
non il

1
Pseudo-codice: String toTest; if (toTest.matches (A) AND! toTest.matches (B)) {...}
Ben S

Avrei dovuto essere più chiaro: i pezzi non sono completamente indipendenti. Se A corrisponde a una parte della stringa, ci importa se ~ B corrisponde al resto di essa (ma non necessariamente all'intera cosa). Questo era per la funzione findstr della riga di comando di Windows, che ho trovato limitata ai veri regex, quindi punto controverso.
non il

8

no, resuscitando questa antica domanda perché aveva una soluzione semplice che non era menzionata. (Ho trovato la tua domanda mentre facevo qualche ricerca per una ricerca di ricompensa regex .)

Sono di fronte a una situazione in cui devo abbinare un modello (A e ~ B).

Il regex di base per questo è spaventosamente semplice: B|(A)

Basta ignorare le partite complessive ed esaminare le acquisizioni del Gruppo 1, che conterrà A.

Un esempio (con tutte le dichiarazioni di non responsabilità sull'analisi dell'html in regex): A è cifre, B è cifre all'interno <a tag

La regex: <a.*?<\/a>|(\d+)

Demo (guarda Gruppo 1 nel riquadro in basso a destra)

Riferimento

Come abbinare il pattern tranne nelle situazioni s1, s2, s3

Come abbinare un modello a meno che ...


Sembra troppo bello per essere vero! Purtroppo, questa soluzione non è universale e non riesce a Emacs, anche dopo la sostituzione \dcon [[:digit:]]. Il primo riferimento indica che è specifico di Perl e PHP: "Esiste una variazione che utilizza la sintassi specifica di Perl e PHP che realizza lo stesso".
miguelmorin,

4

Il complemento di una lingua normale è anche una lingua normale, ma per costruirla è necessario creare il DFA per la lingua normale e trasformare qualsiasi errore valido nello stato in un errore. Vedi questo per un esempio. Ciò che la pagina non dice è che è stata convertita /(ac|bd)/in /(a[^c]?|b[^d]?|[^ab])/. La conversione da un DFA a un'espressione regolare non è banale. È più facile se puoi usare l'espressione regolare invariata e cambiare la semantica nel codice, come suggerito prima.


2
Se avessi a che fare con regex reali, questo sarebbe tutto discutibile. Regex ora sembra riferirsi al nebuloso spazio CSG (?) Di pattern matching che la maggior parte dei linguaggi supporta. Dato che devo abbinare (A e ~ B), non c'è modo di rimuovere la negazione e continuare a fare tutto in un solo passaggio.
non il

Lookahead, come descritto sopra, lo avrebbe fatto se findstr avesse fatto qualcosa al di là delle vere regex DFA. Il tutto è un po 'strano e non so perché devo fare questo stile da riga di comando (batch ora). È solo un altro esempio delle mie mani legate.
non il

1
@notnot: stai usando findstr da Windows? Quindi hai solo bisogno di / v. Come: findstr A inputfile | findstr / v B> outputfile.txt Il primo corrisponde a tutte le righe con A, il secondo a tutte le righe che non hanno B.
Juliano

Grazie! In realtà è esattamente quello di cui avevo bisogno. Non ho fatto la domanda in quel modo, quindi continuo a dare la risposta a Gumbo per la risposta più generalizzata.
non il

1

modello - re

str.split(/re/g) 

restituirà tutto tranne il modello.

Prova qui


Probabilmente vuoi dire che devi iscriverti di nuovo.
tomdemuyt,

Viene utilizzato un approccio simile replace str.replace(/re/g, ''), quindi non è necessario ricongiungersi. anche se lanci un bel finale? come str.replace(/\re\s?/g, '')allora ti sbarazzi di qualsiasi spazio duplicato che potresti avere da qualcosa che viene sostituito nel mezzo di una stringa
jakecraige

0

La mia risposta qui potrebbe risolvere anche il tuo problema:

https://stackoverflow.com/a/27967674/543814

  • Invece di Sostituisci, dovresti usare Abbina.
  • Invece del gruppo $1, dovresti leggere il gruppo $2.
  • Il gruppo è $2stato reso non-cattura lì, cosa che eviteresti.

Esempio:

Regex.Match("50% of 50% is 25%", "(\d+\%)|(.+?)");

Il primo gruppo di acquisizione specifica il modello che si desidera evitare. L'ultimo gruppo di acquisizione cattura tutto il resto. Basta leggere quel gruppo $2,.


0
(B)|(A)

quindi utilizza ciò che il gruppo 2 acquisisce ...


Ha bisogno di catturare non B, il suo obiettivo non è semplicemente quello di ignorare tutti i modelli B.
hexicle,
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.