Successivo: Separatori di campo, Precedente: Campi non costanti, Su: Leggere file [Contenuti][Indice]
Il contenuto di un campo, così come è visto da awk
, può essere
cambiato all’interno di un programma awk
; questo cambia quello che
awk
percepisce come record in input corrente. (Il reale file in
input non viene toccato; awk
non modifica mai il file in
input).
Si consideri il seguente esempio e il suo output:
$ awk '{ numero_pacchi = $3 ; $3 = $3 - 10 > print numero_pacchi, $3 }' inventory-shipped -| 25 15 -| 32 22 -| 24 14 …
Il programma per prima cosa salva il valore originale del campo tre nella
variabile numero_pacchi
.
Il segno ‘-’ rappresenta la sottrazione, così questo programma riassegna
il campo tre, $3
, come il valore originale del campo meno dieci:
‘$3 - 10’. (Vedi la sezione Operatori aritmetici.)
Poi stampa il valore originale e quello nuovo del campo tre.
(Qualcuno nel magazzino ha fatto un errore ricorrente nell’inventariare le
scatole rosse.)
Perché questo funzioni, il testo in $3
deve poter essere riconosciuto
come un numero; la stringa di caratteri dev’essere convertita in un numero
affiché il computer possa eseguire operazioni aritmetiche su di essa. Il
numero che risulta dalla sottrazione viene nuovamente convertito in
una stringa di caratteri che quindi diventa il campo tre.
Vedi la sezione Conversione di stringhe e numeri.
Quando il valore di un campo è cambiato (come percepito da awk
), il
testo del record in input viene ricalcolato per contenere il nuovo campo al
posto di quello vecchio. In altre parole, $0
cambia per riflettere il
campo modificato. Questo programma
stampa una copia del file in input, con 10 sottratto dal secondo campo di ogni
riga:
$ awk '{ $2 = $2 - 10; print $0 }' inventory-shipped -| Jan 3 25 15 115 -| Feb 5 32 24 226 -| Mar 5 24 34 228 …
È possibile inoltre assegnare contenuti a campi che sono fuori intervallo. Per esempio:
$ awk '{ $6 = ($5 + $4 + $3 + $2) > print $6 }' inventory-shipped -| 168 -| 297 -| 301 …
Abbiamo appena creato $6
, il cui valore è la somma dei campi
$2
, $3
, $4
e $5
. Il segno ‘+’
rappresenta l’addizione. Per il file inventory-shipped, $6
rappresenta il numero totale di pacchi spediti in un determinato mese.
La creazione di un nuovo campo cambia la copia interna di awk
nel
record in input corrente, che è il valore di $0
. Così, se si scrive
‘print $0’ dopo aver aggiunto un campo, il record stampato include il
nuovo campo, col numero di separatori di campo appropriati tra esso e i
campi originariamente presenti.
Questa ridefinizione influenza ed è influenzata da
NF
(il numero dei campi; vedi la sezione Un’introduzione ai campi).
Per esempio, il valore di NF
è impostato al numero del campo più
elevato che è stato creato.
Il formato preciso di $0
è influenzato anche da una funzionalità che
non è ancora stata trattata: il separatore di campo di output,
OFS
, usato per separare i campi (vedi la sezione I separatori di output e come modificarli).
Si noti, comunque, che il mero riferimento a un campo fuori
intervallo non cambia il valore di $0
o di NF
.
Far riferimento a un campo fuori intervallo produce solo una stringa nulla.
Per esempio:
if ($(NF+1) != "") print "non è possibile" else print "è tutto normale"
dovrebbe stampare ‘è tutto normale’, perché NF+1
è certamente
fuori intervallo. (Vedi la sezione L’istruzione if
-else
per maggiori informazioni sulle istruzioni if-else
di awk
.
Vedi la sezione Tipi di variabile ed espressioni di confronto
per maggiori informazioni sull’operatore ‘!=’.)
È importante notare che facendo un assegnamento a un campo esistente cambia
il valore di $0
ma non cambia il valore di NF
,
anche qualora si assegni a un campo la stringa nulla. Per esempio:
$ echo a b c d | awk '{ OFS = ":"; $2 = "" > print $0; print NF }' -| a::c:d -| 4
Il campo è ancora lì; ha solo un valore vuoto, delimitato dai due "due punti" tra ‘a’ e ‘c’. Questo esempio mostra cosa succede se si crea un nuovo campo:
$ echo a b c d | awk '{ OFS = ":"; $2 = ""; $6 = "nuovo" > print $0; print NF }' -| a::c:d::nuovo -| 6
Il campo intermedio, $5
, è creato con un valore vuoto
(indicato dalla seconda coppia di due punti (:
) adiacenti),
e NF
è aggiornato col valore sei.
Decrementando NF
si eliminano i campi
dopo il nuovo valore di NF
e si ricalcola $0
.
(a.b.)
Vediamo un esempio:
$ echo a b c d e f | awk '{ print "NF =", NF; > NF = 3; print $0 }' -| NF = 6 -| a b c
ATTENZIONE: Alcune versioni di
awk
non ricostruiscono$0
quandoNF
viene diminuito. Fino ad agosto 2018, fra queste c’era BWKawk
; per fortuna da allora la sua versione funziona correttamente.
Infine, ci sono casi in cui conviene forzare
awk
a ricostruire l’intero record, usando i valori correnti
dei campi e OFS
. Per far ciò, si usa
l’apparentemente innocuo assegnamento:
$1 = $1 # forza la ricostruzione del record print $0 # o qualsiasi altra cosa con $0
Questo forza awk
a ricostruire il record. Aggiungere un commento
rende tutto più chiaro, come abbiamo appena visto.
C’è un rovescio della medaglia nella relazione tra $0
e
i campi. Qualsiasi assegnamento a $0
fa sì che il record sia
rianalizzato (sintatticamente) e ridiviso in campi usando il valore
corrente di FS
. Questo si applica anche a qualsiasi funzione
predefinita che aggiorna $0
, come sub()
e gsub()
(vedi la sezione Funzioni di manipolazione di stringhe).
Comprendere
$0
È importante ricordare che È un errore comune tentare di cambiare il separatore di campo in un record
semplicemente impostando Questo non funziona, poiché non è stato fatto niente per cambiare quello stesso record. Invece, si deve forzare la ricostruzione del record, tipicamente con un’istruzione come ‘$1 = $1’, come descritto in precedenza. |
Successivo: Separatori di campo, Precedente: Campi non costanti, Su: Leggere file [Contenuti][Indice]