Asserzioni
L'asserzione è un test basato su un carattere, che può precedere
o seguire l'attuale punto di riconoscimento, e non consuma
alcun carattere. Le semplici asserzioni quali \b, \B, \A, \Z,
\z, ^ e $ sono state descritte precedentemente. Asserzioni più
complesse possono essere strutturate come delle sotto-regole. Se ne hanno
di due tipologie: quelle che guardano avanti alla posizione attuale
nella stringa oggetto del riconoscimento, e quelle che guardano dietro la posizione attuale.
Una asserzione definita come sotto-regola esegue il riconoscimento
nel modo usuale, ma tale riconoscimento non sposta la posizione
attuale nella stringa. Le asserzioni che "guardano avanti" cominciano
per "(?=", se sono positive, per "(?!", se sono asserzioni negative. Ad esempio
\w+(?=;)
riconosce una parola seguita da ";", ma non include il
punto e virgola nel riconoscimento, mentre
foo(?!bar)
identifica qualsiasi occorrenza di "foo" che non sia seguita da
"bar". Attenzione che il criterio, apparentemente simile,
(?!foo)bar
non riconosce alcuna occorrenza di "bar" se questa è preceduta
da qualsiasi testo che non sia "foo"; infatti l'espressione
riconosce qualsiasi occorrenza di "bar", poiché l'asserzione (?!foo)
è sempre true
quando i tre caratteri successivi sono "bar".
Pertanto è necessario una asserzione che "guarda" all'indietro per ottenere effetto desiderato.
Le asserzioni che "guardano" indietro positive iniziano con
"(?<=", e con "(?<!" le negative. Ad esempio:
(?<!foo)bar
riconosce una occorrenza di "bar" che non sia preceduta da
"foo". Le asserzioni che "guardano" indietro hanno una limitazione:
tutte le stringhe che riconoscono devono avere lunghezza fissa.
Mentre, se si hanno casi alternativi, la limitazione della lunghezza
fissa non sussiste. Quindi
(?<=bullock|donkey)
è una asserzione permessa, ma
(?<!dogs?|cats?)
genera un errore durante la fase di compilazione. Rami alternativi
con lunghezze di stringa differenti sono permessi solo
al primo livello dell'asserzione. Questa è da considerarsi una
estensione rispetto a Perl 5.005, che richiede a tutte le alternative
possibili la medesima lunghezza di stringa. Quindi una asserzione tipo
(?<=ab(c|de))
non è permessa, poiché il suo singolo ramo di primo livello
può identificare testi di due lunghezze differenti, ma è accettabile
se riscritta usando due alternative di primo livello:
(?<=abc|abde)
L'implementazione di questo tipo di asserzioni consiste, per ciascuna
alternativa, di uno spostamento all'indietro temporaneo per la lunghezza
fissa necessaria, e ad un tentativo di riconoscimento del testo. Se non
ci sono sufficienti caratteri precedenti alla posizione attuale,
l'asserzione è destinata a fallire. L'uso accoppiato delle asserzioni
che "guardano" indietro con sotto-regole a riconoscimento singolo può essere utile
per identificare la fine dei testi; un esempio è illustrato al termine
della sezione sulle sotto-regole a riconoscimento singolo.
Diverse asserzioni (di qualsiasi tipologia) possono essere
utilizzate in modo consecutivo. Ad esempio:
(?<=\d{3})(?<!999)foo
riconosce "foo" preceduto da tre cifre che non siano "999".
Occorre rilevare che ciascuna asserzione viene applicata
singolarmente sul medesimo punto nella stringa oggetto di
riconoscimento. Nell'esempio precedente per prima cosa si
verifica che i tre caratteri precedenti siano cifre, quindi
che non siamo "999". Questo esempio non identifica il testo
se "foo" è preceduto da sei caratteri di cui i primi tre siano
cifre e i secondi tre non siano "999". In pratica il testo
"123abcfoo" non viene riconosciuto. Un criterio per riconoscere tale stringa può essere:
(?<=\d{3}...)(?<!999)foo
In questo caso la prima asserzione controlla i primi sei caratteri
verificando che i primi tre siano cifre, mentre la seconda
asserzione verifica che i secondi tre caratteri non siano
"999".
Le asserzioni possono essere annidate in qualsiasi combinazione. Il seguente esempio
(?<=(?<!foo)bar)baz
identifica il testo "baz" se è preceduto da "bar" il quale
non deve essere preceduto da "foo", mentre
(?<=\d{3}...(?<!999))foo
è un'altro criterio che riconosce "foo" preceduto da tre cifre
e da tre caratteri che non siano "999".
Le asserzioni definite come sotto-regole non catturano parte
del testo e non possono essere ripetute (non avrebbe senso
ripetere il medesimo riconoscimento sul medesimo testo).
Se una di queste asserzioni contiene una sotto-regola di cattura
questa viene conteggiata ai fini della numerazione delle regole
di cattura. Tuttavia il testo viene effettivamente catturato
solo nelle asserzioni positive, dato che non avrebbe senso farlo
in quelle negative.
Le asserzioni possono essere composte fino ad un massimo
di 200 sotto-regole.