Su: Funzioni per stringhe   [Contenuti][Indice]


9.1.3.1 Ulteriori dettagli su ‘\’ e ‘&’ con 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.

 Immissione      sub() vede    sub() genera
 —————          ————-          —————
     \&                  &                  Il testo individuato
    \\&                 \&                  La lettera ‘&\\\&                 \&                  La lettera ‘&\\\\&                \\&                  Le lettere ‘\&\\\\\&                \\&                  Le lettere ‘\&\\\\\\&               \\\&                  Le lettere ‘\\&\\q                 \q                  Le lettere ‘\q

Tabella 9.1: Elaborazione storica delle sequenze di protezione per sub() e gsub()

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.

Immissione              sub() vede         sub() genera
———         ———-         —————
\\\\\\&           \\\&            Il carattere ‘\&\\\\&            \\&            Il carattere ‘\’, seguito dal testo individuato
    \\&             \&            Il carattere ‘&\\q             \q            I caratteri ‘\q\\\\             \\            \\

Tabella 9.2: Regole gawk per sub() e barra inversa

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.

Immissione         sub() vede         sub() genera
———         ———-         —————
\\\\\\&           \\\&            I caratteri ‘\&\\\\&            \\&            Il carattere ‘\’, seguito dal testo individuato
    \\&             \&            Il carattere ‘&\\q             \q            I caratteri ‘\q\\\\             \\            \

Tabella 9.3: Regole POSIX per sub() e gsub()

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.

 Immissione          gensub() vede         gensub() genera
 ———          ————-         ——————
      &                    &            Il testo individuato
    \\&                   \&            Il carattere ‘&\\\\                   \\            Il carattere ‘\\\\\&                  \\&            Il carattere ‘\’, seguito dal testo individuato
\\\\\\&                 \\\&            I caratteri ‘\&\\q                   \q            Il carattere ‘q

Tabella 9.4: Elaborazione sequenze di protezione in gensub()

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.


Note a piè di pagina

(51)

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]