Regex lookahead, lookbehind e gruppi atomici


314

Ho trovato queste cose nel mio corpo regex ma non ho idea di cosa posso usarle. Qualcuno ha degli esempi così posso provare a capire come funzionano?

(?!) - negative lookahead
(?=) - positive lookahead
(?<=) - positive lookbehind
(?<!) - negative lookbehind

(?>) - atomic group

18
Perché il sito web regex non ha una tabella semplice come questa? Invece hanno blocchi di testo che spiegano solo. regular-expressions.info/lookaround.html
Whitecat,

3
@Whitecat Prova: regex101.com regexr.com
Andrew

Risposte:


852

Esempi

Data la stringa foobarbarfoo:

bar(?=bar)     finds the 1st bar ("bar" which has "bar" after it)
bar(?!bar)     finds the 2nd bar ("bar" which does not have "bar" after it)
(?<=foo)bar    finds the 1st bar ("bar" which has "foo" before it)
(?<!foo)bar    finds the 2nd bar ("bar" which does not have "foo" before it)

Puoi anche combinarli:

(?<=foo)bar(?=bar)    finds the 1st bar ("bar" with "foo" before it and "bar" after it)

definizioni

Guarda avanti positivo (?=)

Trova l'espressione A dove segue l'espressione B:

A(?=B)

Guarda avanti negativo (?!)

Trova l'espressione A dove l'espressione B non segue:

A(?!B)

Guarda dietro positivo (?<=)

Trova l'espressione A dove l'espressione B precede:

(?<=B)A

Guarda dietro negativo (?<!)

Trova l'espressione A dove l'espressione B non precede:

(?<!B)A

Gruppi atomici (?>)

Un gruppo atomico esce da un gruppo e getta via schemi alternativi dopo il primo schema abbinato all'interno del gruppo (il backtracking è disabilitato).

  • (?>foo|foot)sapplicato a footscorrisponderà alla sua prima alternativa foo, quindi fallirà poiché snon segue immediatamente e si interromperà poiché il backtracking è disabilitato

Un gruppo non atomico consentirà il backtracking; se la corrispondenza successiva in avanti fallisce, tornerà indietro e utilizzerà modelli alternativi fino a quando non viene trovata una corrispondenza per l'intera espressione o tutte le possibilità sono esaurite.

  • (foo|foot)sapplicato alla footsvolontà:

    1. abbina la sua prima alternativa foo, quindi fallisci perché snon segue immediatamente footse torna indietro alla sua seconda alternativa;
    2. abbina la sua seconda alternativa foot, poi corri come ssegue immediatamente footse fermati.

Alcune risorse

Tester online


1
Cosa intendi con "trova la seconda barra"? C'è solo una barra nell'espressione / stringa. Grazie
ziggy

2
@ziggy la stringa in fase di test è "foobarbarfoo". Come puoi vedere ci sono due foo e due bar nella stringa.
skyfoot,

4
Qualcuno può spiegare quando potrebbe essere necessario un gruppo atomico? Se devo solo abbinare la prima alternativa, perché dovrei voler offrire più alternative?
Arviman,

2
Una migliore spiegazione sul gruppo atomico a questa risposta . Qualcuno può modificare qui per completare questa risposta didattica?
Peter Krauss,

5
Solo una nota che questa risposta era essenziale quando sono finito su un progetto che richiedeva costolette di regex. Questa è una spiegazione eccellente e concisa degli sguardi.
Tom Coughlin

215

I lookaround sono affermazioni di larghezza zero. Controllano la presenza di una regex (verso destra o sinistra della posizione corrente - basata su avanti o dietro), ha successo o fallisce quando viene trovata una corrispondenza (basata su se è positiva o negativa) e scarta la parte corrispondente. Non consumano alcun carattere - la corrispondenza per regex che li segue (se presente), inizierà nella stessa posizione del cursore.

Leggi regular-expression.info per maggiori dettagli.

  • Lookahead positivo:

Sintassi:

(?=REGEX_1)REGEX_2

Abbina solo se REGEX_1 corrisponde; dopo aver abbinato REGEX_1, l'incontro viene scartato e la ricerca di REGEX_2 inizia nella stessa posizione.

esempio:

(?=[a-z0-9]{4}$)[a-z]{1,2}[0-9]{2,3}

REGEX_1 [a-z0-9]{4}$corrisponde a quattro caratteri alfanumerici seguiti dalla fine della riga.
REGEX_2 [a-z]{1,2}[0-9]{2,3}corrisponde a una o due lettere seguite da due o tre cifre.

REGEX_1 si assicura che la lunghezza della stringa sia effettivamente 4, ma non consuma alcun carattere in modo che la ricerca di REGEX_2 inizi nella stessa posizione. Ora REGEX_2 si assicura che la stringa corrisponda ad altre regole. Senza guardare avanti corrisponderebbe a stringhe di lunghezza tre o cinque.

  • Lookahead negativo

Sintassi:

(?!REGEX_1)REGEX_2

Abbina solo se REGEX_1 non corrisponde; dopo aver verificato REGEX_1, la ricerca di REGEX_2 inizia nella stessa posizione.

esempio:

(?!.*\bFWORD\b)\w{10,30}$

La parte di ricerca controlla FWORDla stringa nella stringa e non riesce se la trova. Se non trova FWORD, la ricerca ha esito positivo e la parte seguente verifica che la lunghezza della stringa sia compresa tra 10 e 30 e che contenga solo caratteri di parolea-zA-Z0-9_

Look-behind è simile al look-ahead: guarda solo dietro l'attuale posizione del cursore. Alcuni tipi di regex come javascript non supportano le affermazioni look-behind. E la maggior parte dei sapori che lo supportano (PHP, Python ecc.) Richiedono che la parte di ricerca abbia una lunghezza fissa.

  • I gruppi atomici scartano / dimenticano sostanzialmente i token successivi nel gruppo una volta che un token corrisponde. Controlla questa pagina per esempi di gruppi atomici

seguendo la tua spiegazione, sembra non funzionare in javascript, /(?=source)hello/.exec("source...hummhellosource ") = null. La tua spiegazione è corretta?
Helin Wang,

@HelinWang Questa spiegazione è corretta. Il tuo regex si aspetta una stringa che sia sia sorgente che ciao allo stesso tempo!
Amarghosh,

@jddxf Ti interessa elaborare?
Amarghosh,

@Amarghosh Sono d'accordo con "Controllano la presenza di una regex (verso destra o sinistra della posizione corrente - basata su avanti o indietro), ha successo o fallisce quando viene trovata una corrispondenza (basata su se è positiva o negativa) e scarta la corrispondenza porzione.". Quindi lookahead dovrebbe verificare la presenza di una regex verso destra della posizione corrente e la sintassi di lookahead positivo dovrebbe essere x (? = Y)
jddxf

@Amarghosh si abbinerebbe (?=REGEX_1)REGEX_2solo se REGEX_2verrà dopo REGEX_1 ?
aandis,

0

Il trekking è rapido.
Come distinguere lookahead e lookbehind? Fai un tour di 2 minuti con me:

(?=) - positive lookahead
(?<=) - positive lookbehind

supporre

    A  B  C #in a line

Ora chiediamo a B, dove sei?
B ha due soluzioni per dichiararlo posizione:

Uno, B ha A davanti e ha C dietro
Due, B è davanti (guarda avanti) di C e dietro (guarda dietro) A.

Come possiamo vedere, dietro e davanti sono opposti nelle due soluzioni.
Regex è la soluzione due.

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.