Successivo: , Precedente: , Su: regexp Perl   [Contenuti][Indice]


B.8 Dichiarazioni

Una dichiarazione è un test sul carattere che segue o precede il punto di corrispondenza corrente, e tale test non "utilizza" alcun carattere. Le semplici dichiarazioni scritta come \b, \B, \A, \Z, \z, ^ e $ sono descritte sopra. Dichiarazioni più complesse sono scritte come sotto-espressioni. Ce ne sono di due tipi: quelle rivolte in avanti [look ahead] rispetto alla posizione corrente nella stringa in esame, e quelle rivolte all’indietro [look behind].

Una sotto-espressione dichiarativa trova corrispondenza nella maniera solita, tranne per il fatto che non provoca un cambiamento nella posizione attuale raggiunta all’interno della stringa in esame. Le espressioni rivolte in avanti iniziano con (?= per dichiarazioni positive, e con (?! per dichiarazioni negative. Per esempio

\w+(?=;)

corrisponde a una parola seguita da un punto e virgola, ma il punto e virgola non fa parte della stringa trovata, e

foo(?!bar)

corrisponde a qualsiasi occorrenza di ‘foo’ che non sia seguita da ‘bar’.

Si noti che l’espressione regolare apparentemente simile

(?!foo)bar

non trova una ricorrenza di ‘bar’ che sia preceduta da qualcosa di diverso da ‘foo’. Per conseguire quest’effetto è però richiesta una dichiarazione rivolta all’indietro; altrimenti viene trovata qualsiasi occorrenza di ‘bar’, anche se preceduta da ‘foo’, perché la dichiarazione (?!foo) è sempre vera quando i successivi tre caratteri sono ‘bar’. Le dichiarazioni rivolte all’indietro iniziano con (?<= per dichiarazioni positive, e con (?<! per dichiarazioni negative. Così,

(?<!foo)bar

ottiene l’effetto richiesto di trovare un’occorrenza di ‘bar’ che non sia preceduta da ‘foo’. I contenuti di una dichiarazione rivolta all’indietro sono limitati dal fatto che tutte le stringhe corrispondenti devono avere una lunghezza fissa. Comunque, se ci sono parecchie alternative, queste possono non avere tutte la stessa lunghezza. Questa è un’estensione rispetto a Perl 5.005, il quale invece richiede che a tutte le ramificazioni corrispondano stringhe di uguale lunghezza. Quindi

(?<=dogs|cats|)

è ammesso, ma l’apparentemente equivalente espressione regolare

(?<!dogs?|cats?)

causa una segnalazione di errore al momento della compilazione. Ramificazioni che trovano stringhe di lunghezza differente sono permesse solo al livello più alto di una dichiarazione rivolta all’indietro: una dichiarazione come

(?<=ab(c|de))

non è permessa, perché la sua unica ramificazione al livello più alto può corrispondere a stringhe di due lunghezze differenti, ma è accettabile se viene riscritta per usare due ramificazioni a livello più alto:

(?<=abc|abde)

Tutto questo è richiesto perché le dichiarazioni rivolte all’indietro semplicemente spostano indietro la posizione corrente per una lunghezza pari alla lunghezza fissa di ogni alternativa, e in seguito provano a trovare una corrispondenza. Se non ci sono abbastanza caratteri prima della posizione corrente, la corrispondenza è destinata a non essere trovata. Il rivolgersi all’indietro, insieme con l’uso di sotto-espressioni non rivolte all’indietro possono tornare particolarmente utili per delle corrispondenze alla fine di una stringa; un esempio è disponibile alla fine della sezione sulle sotto-espressioni non rivolte all’indietro.

Numerose dichiarazioni (di ogni genere) possono trovarsi una dopo l’altra. Per esempio,

(?<=\d{3})(?<!999)foo

corrisponde a ‘foo’ preceduto da tre cifre che non siano ‘999’. Si noti che ognuna delle dichiarazioni è applicata indipendentemente allo stesso punto della stringa in esame. Dapprima c’è un controllo per verificare che i precedenti tre caratteri siano tutti delle cifre, e poi un controllo per verificare che quegli stessi tre caratteri non siano ‘999’. A quest’espressione non corrisponde ‘foo’ preceduto da sei caratteri, i primi dei quali siano cifre e gli ultimi tre dei quali non siano ‘999’. Per esempio, non si ha corrispondenza per la stringa ‘123abcfoo’. Un’espressione per trovare una tale corrispondenza è

(?<=\d{3}...)(?<!999)foo

Questa volta la prima dichiarazione è rivolta ai sei caratteri precedenti, controllando che i primi tre siano cifre; poi la seconda dichiarazione controlla che i precedenti tre caratteri non siano ‘999’. In realtà, le dichiarazioni possono essere nidificate in qualsiasi combinazione, e quindi si può scrivere questo come:

(?<=\d{3}(?!999)...)foo

oppure

(?<=\d{3}...(?<!999))foo

le quali possono essere considerate entrambe più leggibili.

Le sotto-espressioni di dichiarazione sono sotto-espressioni non di cattura, e non possono essere ripetute, perché non ha senso dichiarare la stessa cosa più volte. Se qualsiasi tipo di dichiarazione contiene sotto-espressioni di cattura al suo interno, queste sono tenute in conto ai fini della numerazione delle sotto espressioni di cattura dell’intera espressione. Comunque, la cattura delle sotto-stringhe è fatta solo per dichiarazioni positive, perché non ha senso farla per dichiarazioni negative.

Le dichiarazioni sono incluse nel conteggio per arrivare al massimo di 200 sotto-espressioni fra parentesi consentite.


Successivo: , Precedente: , Su: regexp Perl   [Contenuti][Indice]