Successivo: , Su: Tipi di variabile e confronti   [Contenuti][Indice]


6.3.2.1 Tipo stringa rispetto a tipo numero

Per gli elementi scalari in awk (variabili, elementi di vettore e campi), il tipo degli stessi viene attribuito dinamicamente. Ciò significa che il tipo di un elemento può cambiare nel corso dell’esecuzione di un programma, da untyped (non ancora tipizzata), valore assunto prima che la variabile sia utilizzata,33 a stringa oppure a numero, e in seguito da stringa a numero o da numero a stringa, nel prosieguo del programma. (gawk prevede anche degli scalari di tipo regexp, ma per ora possiamo ignorarli; vedi la sezione Costanti regexp fortemente tipizzate.)

Non si può fare molto riguardo alle variabili di tipo untyped, oltre a constatare che ancora non è stato loro attribuito un tipo. Il seguente programma confronta la variabile a con i valori "" e 0; il confronto dà esito positivo se alla variabile a non è mai stato assegnato un valore. L’esempio usa la funzione predefinita typeof() (non ancora trattata; vedi la sezione Funzioni per conoscere il tipo di una variabile) per visualizzare il tipo della variabile a:

$ gawk 'BEGIN { print (a == "" && a == 0 ?
> "a non ha un tipo" : "a ha un tipo!") ; print typeof(a) }'
-| a non ha un tipo
-| unassigned

Una variabile scalare diviene di tipo numerico quando le viene assegnato un valore numerico, per mezzo di una costante numerica, o tramite un’altra variabile scalare di tipo numerico:

$ gawk 'BEGIN { a = 42 ; print typeof(a)
> b = a ; print typeof(b) }'
number
number

Analogamente, una variabile scalare diviene di tipo stringa quando le viene assegnato come valore una stringa, per mezzo di una costante stringa, o tramite un’altra variabile scalare di tipo stringa:

$ gawk 'BEGIN { a = "quarantadue" ; print typeof(a)
> b = a ; print typeof(b) }'
string
string

Fin qui, tutto semplice e chiaro. Cosa succede, però, quando awk deve trattare dati forniti dall’utente? Il primo caso da considerare è quello dei campi di dati in input. Quale dovrebbe essere l’output del seguente programma?

echo ciao | awk '{ printf("%s %s < 42\n", $1,
                           ($1 < 42 ? "è" : "non è")) }'

Poiché ‘ciao’ è un dato di tipo alfabetico, awk può solo effettuare un confronto di tipo stringa. Internamente, il numero 42 viene convertito in "42" e vengono confrontate le due stringhe di valore "ciao" e "42". Questo è il risultato:

$ echo ciao | awk '{ printf("%s %s < 42\n", $1,
>                            ($1 < 42 ? "è" : "non è")) }'
-| ciao non è < 42

Tuttavia, cosa succede quando un dato utente assomiglia a un numero? Da un lato, in realtà, il dato in input è formato da alcuni caratteri, non da valori numerici in formato binario. Ma, d’altro lato, il dato sembra numerico, e awk dovrebbe davvero trattarlo come tale. E in effetti questo è ciò che avviene:

$ echo 37 | awk '{ printf("%s %s < 42\n", $1,
>                            ($1 < 42 ? "è" : "non è")) }'
-| 37 is < 42

Queste sono le regole seguite per determinare quando awk tratta dei dati in input come numeri, e quando li considera stringhe.

Lo standard POSIX usa il concetto di stringa numerica, per dei dati in input che appaiono essere numerici. Il ‘37’ nell’esempio precedente è una stringa numerica. Quindi, qual è il tipo di una stringa numerica? Risposta: numerico.

Il tipo di una variabile è importante perché il tipo di due variabili determina il modo con cui le stesse vengono confrontate. La determinazione del tipo di variabile segue queste regole:

L’ultima regola è particolarmente importante. Nel seguente programma, a è di tipo numerico, anche se viene usata in un secondo momento in un’operazione di stringa:

BEGIN {
     a = 12.345
     b = a " è un numero carino"
     print b
}

Quando si confrontano due operandi, può essere usata sia il confronto come stringa che il confronto numerico, a seconda degli attributi degli operandi, secondo questa matrice simmetrica:

        +----------------------------------------------
        |       STRING          NUMERIC         STRNUM
--------+----------------------------------------------
        |
STRING  |       string          string          string
        |
NUMERIC |       string          numeric         numeric
        |
STRNUM  |       string          numeric         numeric
--------+----------------------------------------------

L’idea di base è che l’input dell’utente che appare come numerico — e solo l’input dell’utente — dovrebbe essere trattato come numerico, anche se in realtà è un insieme di caratteri e quindi anche una stringa. Così, ad esempio, la costante di stringa " +3.14", quando appare nel codice sorgente di un programma, è una stringa — anche se sembra numerica — e non viene mai trattato come numero ai fini di un confronto.

In breve, quando un operando è una stringa “pura”, come una costante di stringa, viene effettuato un confronto di stringa. In caso contrario viene effettuato un confronto numerico. (La differenza principale tra un numero e uno strnum è che per gli strnum gawk conserva anche il valore originale della stringa che la variabile scalare aveva al momento in cui è stata letta.

Questo punto merita di essere ulteriormente ribadito: l’input che appare essere un numero è numerico. Tutto il resto dell’input è considerato essere una stringa.

Così, la stringa in input di sei caratteri ‘ +3.14 riceve l’attributo strnum. Al contrario, la stringa di sei caratteri " +3.14" che compaia nel testo di un programma rimane una costante di stringa. I seguenti esempi stampano ‘1’ quando il confronto fra due diverse costanti è vero, altrimenti stampano ‘0’:

$ echo ' +3.14' | awk '{ print($0 == " +3.14") }'    Vero
-| 1
$ echo ' +3.14' | awk '{ print($0 == "+3.14") }'     Falso
-| 0
$ echo ' +3.14' | awk '{ print($0 == "3.14") }'      Falso
-| 0
$ echo ' +3.14' | awk '{ print($0 == 3.14) }'        Vero
-| 1
$ echo ' +3.14' | awk '{ print($1 == " +3.14") }'    Falso
-| 0
$ echo ' +3.14' | awk '{ print($1 == "+3.14") }'     Vero
-| 1
$ echo ' +3.14' | awk '{ print($1 == "3.14") }'      Falso
-| 0
$ echo ' +3.14' | awk '{ print($1 == 3.14) }'        Vero
-| 1

Per controllare il tipo di un campo in input (o di altro input immesso dall’utente, si può usare typeof():

$ echo salve 37 | gawk '{ print typeof($1), typeof($2) }'
-| string strnum

Note a piè di pagina

(33)

gawk chiama queste variabili unassigned (non ancora assegnate), come si vede dall’esempio che segue.

(34)

Quindi, una stringa numerica POSIX e una variabile tipo strnum di gawk sono equivalenti.


Successivo: , Su: Tipi di variabile e confronti   [Contenuti][Indice]