Ricerca…


Nozioni di base

I riferimenti posteriori vengono utilizzati per abbinare lo stesso testo precedentemente abbinato a un gruppo di cattura. Questo aiuta sia a riutilizzare parti precedenti del tuo modello sia a garantire due pezzi di una corrispondenza di stringa.

Ad esempio, se stai cercando di verificare che una stringa abbia una cifra da zero a nove, un separatore, come trattini, barre o spazi, una lettera minuscola, un altro separatore, quindi un'altra cifra da zero a nove, potresti usa una espressione regolare come questa:

[0-9][-/ ][a-z][-/ ][0-9]

Questo corrisponderebbe a 1-a-4 , ma corrisponderebbe anche a 1-a/4 o 1 a-4 . Se vogliamo che i separatori corrispondano, possiamo usare un gruppo di cattura e un riferimento alla parte posteriore. Il riferimento posteriore esaminerà la corrispondenza trovata nel gruppo di cattura indicato e si assicurerà che la posizione del riferimento posteriore corrisponda esattamente.

Usando il nostro stesso esempio, la regex diventerebbe:

[0-9]([-/ ])[a-z]\1[0-9]

Il \1 indica il primo gruppo di cattura nel modello. Con questa piccola modifica, la regex ora corrisponde a 1-a-4 o 1 a 4 ma non a 1 a-4 o 1-a/4 .

Il numero da utilizzare per il riferimento posteriore dipende dalla posizione del gruppo di acquisizione. Il numero può essere compreso tra uno e nove e può essere trovato contando i gruppi di cattura.

([0-9])([-/ ])[a-z][-/ ]([0-9])
|--1--||--2--|          |--3--|

I gruppi di cattura annidati cambiano leggermente questo conteggio. Per prima cosa conta il gruppo di acquisizione esterno, quindi il livello successivo e continua fino a quando non esci dal nido:

(([0-9])([-/ ]))([a-z])
 |--2--||--3--|
|-------1------||--4--|

Backreferences ambigue

Problema: è necessario abbinare il testo di un determinato formato, ad esempio:

1-a-0
6/p/0
4 g 0

Questa è una cifra, un separatore (uno di - , / , o uno spazio), una lettera, lo stesso separatore e uno zero.

Soluzione ingenua: adattando la regex dell'esempio di base , si arriva a questa regex:

[0-9]([-/ ])[a-z]\10

Ma probabilmente non funzionerà. La maggior parte degli aromi regex supportano più di nove gruppi di cattura, e pochissimi sono abbastanza intelligenti da rendersi conto che, poiché esiste un solo gruppo di cattura, \10 deve essere un riferimento al gruppo 1 seguito da uno 0 letterale. La maggior parte degli aromi li tratterà come un retrocesso del gruppo 10. Alcuni di questi genereranno un'eccezione perché non c'è un gruppo 10; il resto semplicemente non riuscirà a eguagliare.

Esistono diversi modi per evitare questo problema. Uno è quello di utilizzare i gruppi denominati (e le relative chiamate di ritorno):

[0-9](?<sep>[-/ ])[a-z]\k<sep>0

Se il tuo linguaggio regex lo supporta, il formato \g{n} (dove n è un numero) può racchiudere il numero di riferimento in parentesi graffe per separarlo da qualsiasi cifra dopo di esso:

[0-9]([-/ ])[a-z]\g{1}0

Un altro modo è usare la formattazione estesa delle espressioni regolari, separando gli elementi con spazi bianchi insignificanti (in Java è necessario sfuggire allo spazio tra parentesi):

(?x) [0-9] ([-/ ]) [a-z] \1 0

Se il tuo sapore regex non supporta queste caratteristiche, puoi aggiungere sintassi non necessaria ma innocua, come un gruppo non catturante:

[0-9]([-/ ])[a-z](?:\1)0

... o un quantificatore fittizio (questa è probabilmente l'unica circostanza in cui {1} è utile):

[0-9]([-/ ])[a-z]\1{1}0


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow