Introduzione
Tipicamente, quando scriviamo script bash, usiamo echo
per stampare sullo standard output. echo
è un comando semplice ma è limitato nelle sue capacità.
Per avere un maggiore controllo sulla formattazione dell'output, utilizzare il comando printf
.
Il comando printf
formatta e stampa i suoi argomenti, in modo simile alla funzione C printf()
.
Comando printf
printf
è una shell integrata in Bash e in altre shell popolari come Zsh e Ksh. Esiste anche un file binario autonomo /usr/bin/printf
, ma la versione integrata della shell ha la precedenza. Tratteremo la versione integrata di Bash di printf
.
La sintassi per il comando printf
è la seguente:
printf [-v var] format [arguments]
L'opzione -v
permette al comando printf
di non stampare l'output ma di assegnarlo a una variabile.
Il parametro format
è una stringa che può contenere tre diversi tipi di oggetti:
- Caratteri normali che sono semplicemente stampati sull'output così come sono.
- Caratteri con backslash che vengono interpretati e quindi stampati.
- Specifiche di conversione che descrivono il formato e sono sostituite dai valori dei rispettivi argomenti che seguono la stringa di formato.
Il comando accetta un numero qualsiasi di arguments
. Se vengono forniti più arguments
di formati, la stringa format
viene riutilizzata per tutti gli arguments
. Se vengono forniti meno arguments
rispetto ai format
, i formati numeri extra vengono impostati su zero mentre i formati stringa extra sono impostati su stringa null.
Di seguito sono riportati alcuni punti da considerare quando si passano gli argomenti al comando printf
:
- La shell sostituirà tutte le variabili, i caratteri wildcard e i caratteri speciali prima di passare gli argomenti al comando
printf
. - Quando si usano virgolette singole
''
il valore letterale di ciascun carattere racchiuso tra virgolette verrà conservato. Variabili e comandi non verranno espansi.
Un tipico esempio di utilizzo di printf
è simile a:
printf "Open issues: %s\nClosed issues: %s\n" "34" "65"
Open issues: 34
Closed issues: 65
La stringa Open issues: %s\nClosed issues: %s\n
è il format
mentre "34" e "65" sono arguments
. La stringa di formato contiene due caratteri di nuova riga (\n
) e due identificatori di formato (%s
) che vengono sostituiti con gli argomenti.
Il comando printf
non aggiunge un carattere di nuova riga (\n
) alla fine della riga.
Caratteri Backslash-escaped
I caratteri con escape backslash vengono interpretati quando utilizzati nella stringa di formato o in un argomento corrispondente a un %b
identificatore di conversione. Ecco un elenco di caratteri di escape più comuni:
\\
- Visualizza un carattere barra rovesciata.\b
- Visualizza un carattere backspace.\n
- Visualizza una nuova riga.\r
- Visualizza un ritorno a capo.\t
- Visualizza una scheda orizzontale.\v
- Visualizza una scheda verticale.
Specifiche di conversione
Una specifica di conversione ha la forma seguente:
%[flags][width][.precision]specifier
Ogni specifica di conversione inizia con il segno di percentuale (%
), include modificatori e fini opzionali con una delle seguenti lettere che rappresentano il tipo di dati (specifier
) dell'argomento corrispondente: aAbcdeEfgGioqsuxX
.
Tipi di identificatori di conversione
La conversione del tipo specifier
è un carattere che specifica come interpretare l'argomento corrispondente. Questo carattere è obbligatorio ed è posizionato dopo i campi opzionali.
Di seguito è riportato un elenco che mostra tutti i tipi di conversioni e ciò che fanno:
%b
- Stampa l'argomento durante l'espansione delle sequenze di escape barra rovesciata (backslash).%q
- Stampa l'argomento citato dalla shell, riutilizzabile come input.%d
,%i
- Stampa l'argomento come intero decimale con segno.%u
- Stampa l'argomento come intero decimale senza segno.%o
- Stampa l'argomento come un numero intero ottale senza segno.%x
,%X
- Stampa l'argomento come intero esadecimale senza segno.%x
stampa lettere minuscole e%X
stampa maiuscole.%e
,%E
- Stampa l'argomento come un numero a virgola mobile in notazione esponenziale.%e
stampa lettere minuscole e%E
stampa maiuscole.%a
,%A
- Stampa l'argomento come un numero a virgola mobile in notazione frazionata esadecimale.%a
stampa lettere minuscole e%A
stampa maiuscole.%g
,%G
- Stampa l'argomento come un numero a virgola mobile in notazione normale o esponenziale, a seconda di quale sia più appropriato per il valore e la precisione dati.%g
stampa lettere minuscole e%G
stampa maiuscole.%c
- Stampa l'argomento come un singolo carattere.%f
- Stampa l'argomento come numero in virgola mobile.%s
- Stampa l'argomento come una stringa.%%
- Stampa un%
simbolo letterale .
Un numero senza segno rappresenta zero e numeri positivi, mentre un numero con segno rappresenta numeri negativi, zero e positivi.
Il seguente comando stampa il numero 100 in tre diversi sistemi di numerazione:
printf "Decimal: %d\nHex: %x\nOctal: %o\n" 100 100 100
Decimal: 100
Hex: 64
Octal: 144
Direttive sui flags
I flag sono i primi modificatori opzionali e vengono utilizzati per impostare la giustificazione, gli zeri iniziali, i prefissi, ecc.
Ecco i più comuni:
-
- Allinea a sinistra il testo stampato all'interno del campo. Per impostazione predefinita, il testo è allineato a destra.+
- Prefisso i numeri con un segno+
o-
. Per impostazione predefinita, solo i numeri negativi sono preceduti da un segno negativo.0
- Pad numeri con zeri iniziali anziché spazio.- vuoto
-
). #
- Un formato alternativo per i numeri.
Direttiva Width
La direttiva width
viene posizionata dopo qualsiasi flag e specifica il numero minimo di caratteri che dovrebbe comportare la conversione.
Se la larghezza del testo emessa è inferiore alla larghezza specificata, viene riempita con spazi. La larghezza può essere specificata come un numero intero decimale non negativo o un asterisco (*
).
Ecco un esempio:
printf "%20s %d\n" Mark 305
%20s
significa impostare il campo di almeno 20 caratteri. Gli spazi vengono aggiunti prima del testo perché, per impostazione predefinita, l'output è giustificato a destra. Per allineare il testo a sinistra, utilizzare il flag -
(%-20s
).
Mark 305
Quando un asterisco (*
) viene utilizzato come direttiva width
, la larghezza del campo di conversione viene impostata da un argomento width che precede l'argomento formattato.
Nell'esempio seguente impostiamo la larghezza su 10:
printf "%0*d" 10 5
0
è un flag che riempie il numero con zeri iniziali anziché spazi vuoti. Il testo di output avrà almeno 10 caratteri:
0000000005
Direttiva Precision
Il modificatore .precision
è costituito da un punto (.
) seguito da un numero intero positivo o da un asterisco (*
) che, in base al tipo di specificatore, imposta il numero di caratteri stringa o cifra o il numero di cifre decimali da stampare.
.precision
ha il seguente effetto:
- Se il tipo di conversione è un numero intero,
precision
specifica il numero minimo di cifre da stampare. Se il numero di cifre nell'argomento è inferiore aprecision
, vengono stampati gli zeri iniziali. - Se il tipo di conversione è in virgola mobile,
precision
specifica il numero di cifre che seguono il carattere in virgola decimale. Di defaultprecision
è di 6. - Se il tipo di conversione è una stringa,
precision
specifica il numero massimo di caratteri da stampare. Se il numero di caratteri nell'argomento è maggiore diprecision
, i caratteri in eccesso vengono troncati.
Ecco un esempio che mostra come arrotondare un numero in virgola mobile a 3 decimali:
printf "%.3f" 1.61803398
1.618
Quando precision
è impostata su un asterisco (*
), il suo valore viene impostato dall'argomento precision
che precede l'argomento che viene formattato.
printf "%.*f" 3 1.61803398
1.618
Conclusione
Il comando printf
accetta un formato e argomenti e stampa un testo formattato.