Successivo: , Precedente: , Su: Storia del linguaggio   [Contenuti][Indice]


A.8 Intervalli regexp e localizzazione: una lunga e triste storia

Questa sezione descrive la storia confusionaria degli intervalli all’interno di espressioni regolari, le loro relazioni con la localizzazione, e l’effetto da ciò determinato su diverse versioni di gawk.

Gli strumenti originali Unix aventi a che fare con espressioni regolari stabilivano che intervalli di caratteri (come ‘[a-z]’) individuavano un carattere qualsiasi tra il primo carattere dell’intervallo e l’ultimo carattere dello stesso, entrambi inclusi. L’ordinamento era basato sul valore numerico di ogni carattere come era rappresentato all’interno del computer, nell’insieme di caratteri proprio di ogni macchina. Quindi, su sistemi che adottano la codifica ASCII, ‘[a-z]’ individua tutte le lettere minuscole, e solo quelle, in quanto i valori numerici che rappresentano le lettere dalla ‘a’ fino alla ‘z’ sono contigui. (In un sistema che adotta la codifica EBCDIC, l’intervallo ‘[a-z]’ comprende anche ulteriori caratteri non alfabetici.)

Quasi tutti i testi di introduzione allo Unix spiegavano che le espressioni di intervallo funzionavano in questo modo, e in particolare insegnavano che la maniera “corretta” per individuare le lettere minuscole era con ‘[a-z]’ e che ‘[A-Z]’ era il modo “corretto” per individuare le lettere maiuscole. E, in effetti, era proprio così.118

Lo standard POSIX 1992 introduceva l’idea di localizzazione (vedi la sezione Il luogo fa la differenza). Poiché molte localizzazioni comprendono altre lettere, oltre alle 26 lettere dell’alfabeto inglese, lo standard POSIX introduceva le classi di carattere (vedi la sezione Usare espressioni tra parentesi quadre) per permettere l’individuazione di differenti insiemi di caratteri, in aggiunta a quelli tradizionali presenti nell’insieme di caratteri ASCII.

Tuttavia, lo standard ha modificato l’interpretazione delle espressioni di intervallo. Nelle localizzazioni "C" e "POSIX", un’espressione di intervallo come ‘[a-dx-z]’ è ancora equivalente a ‘[abcdxyz]’, secondo l’ordine della codifica ASCII. Ma in tutte le altre localizzazioni l’ordinamento è basato su quel che si chiama ordine di collazione.

Cosa vuol dire? In molte localizzazioni, le lettere ‘A’ e ‘a’ vengono entrambe prima di ‘B’. In altre parole, queste localizzazioni ordinano i caratteri nel modo in cui sono ordinati in un dizionario, e ‘[a-dx-z]’ non è detto che equivalga a ‘[abcdxyz]’; invece, potrebbe essere equivalente a ‘[ABCXYabcdxyz]’, per fare un esempio.

Su questo punto è opportuno insistere: molta documentazione afferma che si dovrebbe usare ‘[a-z]’ per identificare un carattere minuscolo. Ma su sistemi con localizzazioni non-ASCII, un tale intervallo potrebbe includere tutti i caratteri maiuscoli tranne ‘A’ o ‘Z’! Questo ha continuato a essere una fonte di equivoci perfino nel ventunesimo secolo.

Per dare un’idea del tipo di problemi, l’esempio seguente usa la funzione sub(), che effettua una sostituzione di testo all’interno di una stringa (vedi la sezione Funzioni di manipolazione di stringhe). Qui, l’idea è quella di rimuovere i caratteri maiuscoli a fine stringa:

$ echo qualcosa1234abc | gawk-3.1.8 '{ sub("[A-Z]*$", ""); print }'
-| qualcosa1234a

Questo non è l’output che ci si aspettava, perché, il ‘bc’ alla fine di ‘qualcosa1234abc’ non dovrebbe essere individuato da ‘[A-Z]*’. Un tale risultato dipende dalle impostazioni di localizzazione (e quindi potrebbe non succedere sul sistema che si sta usando).

Considerazioni simili valgono per altri intervalli. Per esempio, ‘["-/]’ è perfettamente valido in ASCII, ma non è valido in molte localizzazioni Unicode, p.es. in en_US.UTF-8.

Il codice delle prime versioni di gawk per individuare le regexp non teneva conto della localizzazione, e quindi gli intervalli potevano essere interpretati in maniera tradizionale.

Quando gawk ha iniziato a usare metodi di ricerca di regexp che tengono conto della localizzazione, sono iniziati i problemi; a maggior ragione in quanto sia GNU/Linux che i venditori di versioni commerciali di Unix avevano iniziato a implementare localizzazioni non-ASCII, adottandole per default. La domanda che forse si udiva più spesso era del tipo: “Perché ‘[A-Z]’ individua lettere minuscole?!?”

Questa situazione è in essere da circa 10 anni, se non di più, e il manutentore di gawk si è stufato di continuare a spiegare che gawk stava semplicemente implementando quelli che sono gli standard, e che il problema stava nella localizzazione dell’utente. Nella fase di sviluppo della versione 4.0, gawk è stato modificato in modo da trattare sempre gli intervalli "come si faceva prima di POSIX", a meno che non si specifichi l’opzione --posix (vedi la sezione Opzioni sulla riga di comando).119

Fortunatamente, un po’ prima del rilascio definitivo della versione 4.0 di gawk, il manutentore ha appreso che lo standard 2008 aveva modificato la definizione di intervallo, e che, al di fuori delle localizzazioni "C" e "POSIX", il significato di espressione di intervallo era ora indefinito.120

Adottando questo simpatico termine tecnico, lo standard permette agli implementatori di implementare gli intervalli nella maniera che preferiscono. Il manutentore di gawk ha deciso di implementare la regola pre-POSIX sia per l’individuazione di default delle regexp sia quando si specificano le opzioni --traditional o --posix. In ogni caso gawk aderisce allo standard POSIX.


Note a piè di pagina

(118)

E la vita era semplice.

(119)

Ed è così che è nata la Campagna per l’Interpretazione Razionale degli Intervalli (in inglese, RRI [Rational Range Interpretation]). Un certo numero di strumenti GNU hanno già implementato questa modifica, o lo faranno presto. Grazie a Karl Berry per aver coniato la frase “Rational Range Interpretation”.

(120)

Si veda lo standard e le motivazioni.


Successivo: , Precedente: , Su: Storia del linguaggio   [Contenuti][Indice]