Espressioni regolari e annullamento di un intero gruppo di caratteri

Sto tentando qualcosa che ritengo dovrebbe essere abbastanza ovvio per me, ma non lo è. Sto cercando di abbinare una stringa che NON contiene una sequenza specifica di caratteri. Ho provato a usare [^ab] , [^(ab)] , ecc. Per far corrispondere le stringhe che non contengono “a” o “b”, o solo “a” o “solo” o “ba” ma non corrispondono a “ab”. Gli esempi che ho dato non corrispondono a “ab” è vero, ma non corrisponderanno nemmeno a “a” e io ne ho bisogno. C’è un modo semplice per farlo?

Usa lookahead negativo:

 ^(?!.*ab).*$ 

AGGIORNAMENTO: Nei commenti seguenti, ho affermato che questo approccio è più lento di quello indicato nella risposta di Peter . Da allora ho eseguito alcuni test e ho scoperto che è leggermente più veloce. Tuttavia, la ragione per preferire questa tecnica rispetto all’altra non è la velocità, ma la semplicità.

L’altra tecnica, qui descritta come un token goloso temperato , è adatta per problemi più complessi, come la corrispondenza del testo delimitato in cui i delimitatori sono costituiti da più caratteri (come HTML, come commentò Luca sotto ). Per il problema descritto nella domanda, è eccessivo.

Per chiunque sia interessato, ho provato con una grande porzione di testo Lorem Ipsum, contando il numero di righe che non contengono la parola “quo”. Queste sono le regex che ho usato:

 (?m)^(?!.*\bquo\b).+$ (?m)^(?:(?!\bquo\b).)+$ 

Sia che cerco corrispondenze nell’intero testo, sia che le suddivida in righe e le abbini individualmente, il lookahead ancorato sovrasta costantemente quello fluttuante.

L’uso di una class di caratteri come [^ab] corrisponderà a un singolo carattere che non rientra nel set di caratteri. (Con il ^ essendo la parte negativa).

Per abbinare una stringa che non contiene la sequenza multi-carattere ab , si desidera utilizzare un lookahead negativo:

 ^(?:(?!ab).)+$ 

E l’espressione sopra descritta nella modalità commento espressioni regolari è:

 (?x) # enable regex comment mode ^ # match start of line/string (?: # begin non-capturing group (?! # begin negative lookahead ab # literal text sequence ab ) # end negative lookahead . # any single character ) # end non-capturing group + # repeat previous match one or more times $ # match end of line/string 

Sì, è chiamato lookahead negativo. Va così – (?!regex here) . Quindi abc(?!def) corrisponderà ad abc non seguito da def. Quindi abbinerà abce, abc, abck, ecc.

Allo stesso modo c’è un lookahead positivo – (?=regex here) . Quindi abc(?=def) corrisponderà ad abc seguito da def.

Esistono anche aspetti negativi e positivi: (? e (?<=regex here) rispettivamente

Un punto da notare è che il lookahead negativo è a larghezza zero. Cioè, non conta come aver preso alcuno spazio.

Quindi può sembrare a(?=b)c corrisponderà a "abc" ma non lo farà. Corrisponde a 'a', quindi al lookahead positivo con 'b' ma non si sposta in avanti nella stringa. Quindi proverà ad abbinare la 'c' con 'b' che non funzionerà. Allo stesso modo ^a(?=b)b$ corrisponderà a 'ab' e non a 'abb' perché i lookaround sono a larghezza zero (nella maggior parte delle implementazioni di espressioni regolari).

Maggiori informazioni su questa pagina

Usare una regex come hai descritto è il modo semplice (per quanto ne so). Se vuoi un intervallo puoi usare [^ af].

Il modo più semplice è di eliminare completamente la negazione dall’espressione regolare:

 if (!userName.matches("^([Ss]ys)?admin$")) { ... } 

abc (?! def) corrisponderà ad abc non seguito da def. Quindi abbinerà abce, abc, abck, ecc. E se non voglio né def né xyz sarà abc (?! (Def) (xyz)) ???

Ho avuto la stessa domanda e ho trovato una soluzione:

 abc(?:(?!def))(?:(?!xyz)) 

Questi gruppi senza contare sono combinati da “AND”, quindi questo dovrebbe fare il trucco. Spero che sia d’aiuto.

La regex [^ (ab)] corrisponderà ad esempio ‘ab ab ab ab’ ma non ‘ab’, perché corrisponderà alla stringa ‘a’ o ‘b’.

Che lingua / scenario hai? Puoi sottrarre i risultati dal set originale e abbinare semplicemente ab?

Se stai utilizzando GNU grep e stai analizzando l’input, usa il flag ‘-v’ per invertire i risultati, restituendo tutte le non-corrispondenze. Anche altri strumenti di regex hanno una funzione ‘return nonmatch’.

Se ho capito bene, tu vuoi tutto tranne quegli articoli che contengono ‘ab’ ovunque.

In questo caso, potrei semplicemente evitare del tutto le espressioni regolari e utilizzare qualcosa come:

 if (StringToTest.IndexOf("ab") < 0) //do stuff 

Probabilmente questo sarà anche molto più veloce (un rapido test vs regex sopra ha mostrato che questo metodo richiede circa il 25% del tempo del metodo regex). In generale, se conosco la stringa esatta che sto cercando, ho trovato che le regex sono eccessive. Poiché sai che non vuoi "ab", è semplice verificare se la stringa contiene quella stringa, senza usare espressioni regolari.

Basta cercare “ab” nella stringa e quindi annullare il risultato:

 !/ab/.test("bamboo"); // true !/ab/.test("baobab"); // false 

Sembra più facile e dovrebbe essere anche più veloce.