Su: Funzioni per stringhe [Contenuti][Indice]
sub()
, gsub()
e gensub()
ATTENZIONE: Si dice che questa sottosezione possa causare dei mal di testa. In prima lettura può essere benissimo saltata.
Quando si usa sub()
, gsub()
o gensub()
, e si
desidera includere delle
barre inverse e delle "e commerciali" (&
) nel testo da sostituire
è necessario ricordare che ci sono parecchi livelli di
protezione caratteri in gioco.
Anzitutto, vi è il livello lessicale, quello in cui awk
legge un programma e ne costruisce una copia interna da eseguire.
Poi c’è il momento dell’esecuzione, quello in cui awk
esamina effettivamente la stringa da sostituire, per determinare cosa
fare.
In entrambi i livelli, awk
ricerca un dato insieme di caratteri
che possono venire dopo una
barra inversa. A livello lessicale, cerca le sequenze di protezione
elencate in Sequenze di protezione.
Quindi, per ogni ‘\’ che awk
elabora al momento
dell’esecuzione, occorre immetterne due a livello lessicale.
Quando un carattere che non ha necessità di una sequenza di protezione
segue una ‘\’, sia BWK awk
che gawk
semplicemente
rimuovono la ‘\’ stessa e
mettono il carattere seguente nella stringa. Quindi, per esempio,
"a\qb"
è trattato come se si fosse scritto "aqb"
.
Al momento dell’esecuzione, le varie funzioni gestiscono sequenze di
‘\’ e ‘&’ in maniera differente. La situazione è (purtroppo)
piuttosto complessa.
Storicamente, le funzioni sub()
e gsub()
trattavano la
sequenza di due caratteri ‘\&’ in maniera speciale; questa sequenza
era rimpiazzata nel testo
generato da un singolo carattere ‘&’. Ogni altra ‘\’ contenuta
nella stringa rimpiazzo che non era posta prima di una ‘&’ era
lasciata passare senza modifiche.
Questo è illustrato nella Tabella 9.1.
Immissionesub()
vedesub()
genera ————— ————- —————\&
&
Il testo individuato\\&
\&
La lettera ‘&’\\\&
\&
La lettera ‘&’\\\\&
\\&
Le lettere ‘\&’\\\\\&
\\&
Le lettere ‘\&’\\\\\\&
\\\&
Le lettere ‘\\&’\\q
\q
Le lettere ‘\q’
Questa tabella mostra l’elaborazione a livello lessicale, in cui
un numero dispari di barre inverse diventa un numero pari al momento
dell’esecuzione,
e mostra anche l’elaborazione in fase di esecuzione fatta da sub()
.
(Per amor di semplicità le tavole che ancora seguono mostrano solo il caso
di un numero pari di barre inverse immesso a livello lessicale.)
Il problema con l’approccio storico è che non c’è modo di ottenere un carattere ‘\’ seguito dal testo individuato.
Parecchie edizioni dello standard POSIX hanno provato a risolvere questo problema, senza riuscirci. I dettagli sono irrilevanti in questo contesto.
A un certo punto, il manutentore di gawk
ha presentato una
proposta per una revisione dello standard per tornare
a regole che corrispondano più da vicino alla prassi originalmente seguita.
Le regole proposte hanno dei casi speciali che rendono possibile
produrre una ‘\’ prima del
testo individuato. Questo si può vedere nella
Tabella 9.2.
Immissionesub()
vedesub()
genera ——— ———- —————\\\\\\&
\\\&
Il carattere ‘\&’\\\\&
\\&
Il carattere ‘\’, seguito dal testo individuato\\&
\&
Il carattere ‘&’\\q
\q
I caratteri ‘\q’\\\\
\\
\\
In breve, al momento dell’esecuzione, ci sono ora tre sequenze speciali di caratteri (‘\\\&’, ‘\\&’, e ‘\&’) mentre tradizionalmente ce n’era una sola. Tuttavia, come nel caso storico, ogni ‘\’ che non fa parte di una di queste tre sequenze non è speciale e appare nell’output così come è scritto.
gawk
3.0 e 3.1 seguono queste regole per sub()
e
gsub()
. La revisione dello standard POSIX ha richiesto molto più tempo
di quel che ci si attendeva. Inoltre, la proposta del manutentore di
gawk
è andata persa durante il processo di standardizzazione. Le
regole finali risultanti sono un po’ più semplici. I risultati sono simili,
tranne che in un caso.
Le regole POSIX stabiliscono che ‘\&’ nella stringa di rimpiazzo produca il carattere ‘&’, ‘\\’ produce il carattere ‘\’, e che ‘\’ seguito da qualsiasi carattere non è speciale; la ‘\’ è messa direttamente nell’output. Queste regole sono presentate nella Tabella 9.3.
Immissionesub()
vedesub()
genera ——— ———- —————\\\\\\&
\\\&
I caratteri ‘\&’\\\\&
\\&
Il carattere ‘\’, seguito dal testo individuato\\&
\&
Il carattere ‘&’\\q
\q
I caratteri ‘\q’\\\\
\\
\
Il solo caso in cui la differenza è rilevante è l’ultimo: ‘\\\\’ è visto come ‘\\’ e produce ‘\’ invece che ‘\\’.
A partire dalla versione 3.1.4, gawk
ha seguito le regole
POSIX quando si specifica --posix (vedi la sezione Opzioni sulla riga di comando). Altrimenti, ha
continuato a seguire le regole proposte [a POSIX], poiché questa è stato il
comportamento seguito per parecchi anni.
Quando la versione 4.0.0 è stata rilasciata, il manutentore di
gawk
ha stabilito come default le regole POSIX, interrompendo così oltre
un decennio di compatibilità
all’indietro.51
Inutile dire che questa non è stata una buona idea, e quindi dalla
versione 4.0.1, gawk
ha ripreso il suo comportamento
tradizionale, seguendo le regole POSIX solo quando si specifica l’opzione
--posix.
Le regole per gensub()
sono molto più semplici. Al momento
dell’esecuzione, quando gawk
vede una ‘\’, se il carattere
seguente è una cifra,
il testo individuato dalla corrispondente sottoespressione tra parentesi
è inserito nell’output generato. Altrimenti, qualsiasi carattere segua la
‘\’ viene inserito nel testo generato, mentre la ‘\’ va persa,
come si vede nella Tabella 9.4.
Immissionegensub()
vedegensub()
genera ——— ————- ——————&
&
Il testo individuato\\&
\&
Il carattere ‘&’\\\\
\\
Il carattere ‘\’\\\\&
\\&
Il carattere ‘\’, seguito dal testo individuato\\\\\\&
\\\&
I caratteri ‘\&’\\q
\q
Il carattere ‘q’
A causa della complessità dell’elaborazione a livello lessicale e in fase
di esecuzione, e dei casi speciali di sub()
e gsub()
,
si raccomanda l’uso di gawk
e di gensub()
quando ci siano
da fare delle sostituzioni.
Questa decisione si è dimostrata piuttosto avventata,
anche se una nota in questa sezione avvertiva che la successiva versione
principale di gawk
avrebbe adottato le regole POSIX.
Su: Funzioni per stringhe [Contenuti][Indice]