Successivo: Operatori di confronto, Su: Tipi di variabile e confronti [Contenuti][Indice]
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:
getline
, FILENAME
, elementi di
ARGV
, elementi di ENVIRON
, e gli elementi di un vettore
creato da match()
, split()
e patsplit()
che sono
stringhe numeriche hanno l’attributo strnum.34
Altrimenti, hanno l’attributo string.
Anche le variabili non inizializzate hanno l’attributo strnum.
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
gawk
chiama queste variabili unassigned (non ancora assegnate), come si
vede dall’esempio che segue.
Quindi, una
stringa numerica POSIX e una variabile tipo strnum di gawk
sono equivalenti.
Successivo: Operatori di confronto, Su: Tipi di variabile e confronti [Contenuti][Indice]