Dopo la nostra breve puntata volta a comprendere come implementare uno script è sicuramente il caso di effettuare un riepilogo dei principali strumenti CLI concepiti per manipolare i file di testo e quindi anche, ovviamente, la quasi totalità dei file di configurazione, di output e log. Uno degli usi principali degli script infatti consiste proprio nella gestione più o meno automatizzata di questi file.
Prima di ogni altra cosa anticipiamo brevemente il concetto di redirezione dell’output. Esistono vari canali di output utilizzabili per gli script. Di norma sono indirizzati, esemplificando brutalmente, verso lo “schermo”. E’ però possibile redirigerli verso file. Ad esempio digitando eseguibile>file ciò che di norma sarebbe inviato verso il monitor viene riversato nello specifico file che sarà creato o, se questi già esiste, sovrascriscritto. Lo stesso effetto può essere ottenuto usando il doppio maggiore (>>) con la differenza che il file non sarà sovrascritto ma invece riceverà il nuovo output come aggiunta quindi in coda a quanto già presente. E’ anche possibile utilizzare l’output di un eseguibile come input di una altro eseguibile, in modo da fornire in pasto al secondo quanto proviene dal primo. Per ottenere questo effetto frapponete fra i due eseguibili "|" (pipe). Qualche informazione aggiuntiva sulle redirezione potrete trovarla in questa guida.
Entriamo nel vivo degli argomenti accennati in apertura. Negli esempi utilizzeremo un file dati di esempio,
bd.csv, che adotta come separatore le virgole. Eccone una sua rappresentazione tabellare:
Nome | Cognome | |
Mickey | Mouse | topolino@topolinia.dis |
Donald | Duck | paperino@paperopoli.dis |
Gyro | Gearloose | archimede@paperopoli.dis |
Minnie | Mouse | minni@topolinia.dis |
cut
Il primo comando che prenderemo in esame è cut. Può essere adoperato con file di testo concepiti rispettando una struttura relazionale riga-colonna e che abbiano delimitatori rappresentati da caratteri. Il file csv che utilizziamo come esempio contiene un indirizzario. Con cut -d indichiamo il delimitatore adottato, con -f l'ordinale della colonna che intendiamo visualizzare.
fprincipe@html1:~$ cut -f2 -d, bd.csv
Cognome
Mouse
Duck
Gearloose
Mouse
La seconda colonna nel nostro file di esempio è quella che mantiene traccia dei cognomi. Con il comando che avete appena incrociato è quindi possibile, come avete visto, ottenere in risposta una colonna specifica di un file testuale relazionale.
awk
Uno degli strumenti per eccellenza, quando si ha a che fare con gli stream di testo è awk, che può essere utilizzato per isolare le righe che rispondono a determinati criteri. E' estremamente potente e versatile, consigliamo di dare uno sguardo al suo corposo manuale anteponendo al nome dell'applicazione il comando man.
Il piccolo esempio a seguire potrà comunque fornire uno spunto d'uso. Come vedete è possibile isolare le righe in cui è presente oggetto di interesse segnalandola a aws fra due / (slash).
fprincipe@html1:~$ cat bd.csv | awk /Mouse/
Mickey,Mouse,topolino@topolinia.dis
Minnie,Mouse,minni@topolinia.dis
sed
Adesso passiamo a quello che può essere considerato il principe della manipolazione per gli stream di testo. Per effettuare sostituzioni "al volo" possiamo utilizzare sed. Si rivelerà di uso molto agevole anche per la sua intrinseca semplicità infatti risulta più intuitivo descriverne l'utilizzo dopo aver visionato un esempio:
fprincipe@html1:~$ sed /Gyro/d bd.csv
Nome,Cognome,Email
Mickey,Mouse,topolino@topolinia.dis
Donald,Duck,paperino@paperopoli.dis
Minnie,Mouse,minni@topolinia.dis
fprincipe@html1:~$ sed s/dis/org/ bd.csv
Nome,Cognome,Email
Mickey,Mouse,topolino@topolinia.org
Donald,Duck,paperino@paperopoli.org
Gyro,Gearloose,archimede@paperopoli.org
Minnie,Mouse,minni@topolinia.org
fprincipe@html1:~$ sed s/,/\;/ bd.csv
Nome;Cognome,Email
Mickey;Mouse,topolino@topolinia.dis
Donald;Duck,paperino@paperopoli.dis
Gyro;Gearloose,archimede@paperopoli.dis
Minnie;Mouse,minni@topolinia.dis
fprincipe@html1:~$ sed s/,/\;/g bd.csv
Nome;Cognome;Email
Mickey;Mouse;topolino@topolinia.dis
Donald;Duck;paperino@paperopoli.dis
Gyro;Gearloose;archimede@paperopoli.dis
Minnie;Mouse;minni@topolinia.dis
I pattern (ovvero gli schemi che se soddisfatti ne implicano l’attivazione) vengono dichiarati grazie all'uso degli slash. Nell'esempio subito sopra sed viene lanciato più volte sul file di esempio ottenendo sempre un risultato diverso. Con sed /Gyro/d bd.csv chiediamo a sed di scovare la riga contenente il pattern Gyro e di rimuoverla (d richiede un "delete"). Poi chiediamo di cambiare ogni occorrenza dis in org. Subito a seguire facciamo quanto necessario per modificare il separatore decidendo di adottare il punto e virgola in sostituzione della virgola. Alcuni caratteri hanno significati particolari per sed quindi quando intendiamo utilizzarli (in quanto tali e non per la loro funzione specifica) è necessario anteporre uno backslash (\). Con un paio di prove e buttando un occhio al manuale tramite il comando man sed risolverete ogni perplessità in pochi attimi. Nella sostituzione appena effettuata scopriamo che alla prima occorrenza sed scarta la riga e passa alla prossima. Ovviamente esiste la possibilità di estendere l'azione di sed. Per effettuare una sostituzione globale dobbiamo aggiungere la g dichiarando il pattern quale “global” per l’intera riga processata.
diff
Quando effettuiamo modifiche sui file di testo oppure queste sono effettuate automaticamente possiamo trovarci nella necessità di identificare a posteriori i cambiamenti fra due versioni. Ovviamente i file di testo possono essere troppo lunghi per intraprendere manualmente una simile impresa. Un comando può venirci in soccorso.
A fornirci ausilio, questa volta, sarà diff.
Le informazioni che otterremo in risposta, eseguendolo, sono quelle necessarie a rendere due file equivalenti.
L'output non è intuitivo ma compresa la logica con cui è concepito apparirà funzionale. Si procede riga per riga elencando, ovviamente, solo quelle che hanno subito un cambiamento. Il segno di minore (<) indicherà che ci si riferisce al primo file, quello di maggiore (>) al secondo. Ogni modifica sarà segnalata innanzi tutto con numero di riga relativo al primo file, poi leggerete ciò andrebbe fatto per allineare i file ovvero: a per aggiungi, c per cambia, d per cancella. L’ultimo numero è quello relativo alla riga a cui ci si riferisce nel secondo file.
fprincipe@html1:~$ more 1.txt
1 Fff
2 dsf
3 dsff
4 45
5 dsfd
fprincipe@html1:~$ more 2.txt
1 Fff
2 dsf
3 dsff
4 45,
5 dsfd
6 das
fprincipe@html1:~$ diff 1.txt 2.txt
4c4
4 45,
5a6
> 6 das
Altri comandi utili per manipolare file di testo
I comandi precedenti consentono di rispondere a molte esigenze se utilizzati in combinazione con una serie di utilità minori che ora brevemente presentiamo.
E' possibile che in un file di testo siano annidati caratteri che non possono essere rappresentati a schermo. Per scovarli può essere utile fare il “dump” cioè riversare a video un file sfruttando una rappresentazione diversa.
Con bd -b otteniamo una rappresentazione ottale, una decimale utilizzandolo con l'argomento -d, così come esadecimale con l'argomento -x e a caratteri con l'argomento -c.
Ecco un esempio:
fprincipe@html1:~$ od -bc bd.csv
0000000 116 157 155 145 054 103 157 147 156 157 155 145 054 105 155 141
N o m e , C o g n o m e , E m a
0000020 151 154 012 115 151 143 153 145 171 054 115 157 165 163 145 054
i l \n M i c k e y , M o u s e ,
0000040 164 157 160 157 154 151 156 157 100 164 157 160 157 154 151 156
t o p o l i n o @ t o p o l i n
0000060 151 141 056 144 151 163 012 104 157 156 141 154 144 054 104 165
i a . d i s \n D o n a l d , D u
0000100 143 153 054 160 141 160 145 162 151 156 157 100 160 141 160 145
c k , p a p e r i n o @ p a p e
0000120 162 157 160 157 154 151 056 144 151 163 012 107 171 162 157 054
r o p o l i . d i s \n G y r o ,
0000140 107 145 141 162 154 157 157 163 145 054 141 162 143 150 151 155
G e a r l o o s e , a r c h i m
0000160 145 144 145 100 160 141 160 145 162 157 160 157 154 151 056 144
e d e @ p a p e r o p o l i . d
0000200 151 163 012 115 151 156 156 151 145 054 115 157 165 163 145 054
i s \n M i n n i e , M o u s e ,
0000220 155 151 156 156 151 100 164 157 160 157 154 151 156 151 141 056
m i n n i @ t o p o l i n i a .
0000240 144 151 163 012
d i s \n
Qualora dovessimo avere necessità di ordinare una serie di linee è possibile farlo adoperando il comando sort -r.
Un altro comando che può risultare utile è quello che prende in consegna un file di testo, aggiunge una intestazione numerica sequenziale a ogni riga e lo restituisce a video. Potete ottenere questo effetto adoperando nl.
I file di testo contenenti elenchi possono essere formattati adoperando spazi e tabulazioni che rappresentano la separazione fra le colonne. Concludiamo quindi con due comandi poco conosciuto che vi consentono un maggior controllo sulle tabulazioni. Adoperate i comandi unexpand ed expand, con il primo convertirete spazi in tabulazioni e con il secondo farete l'inverso. Per convenzione 8 spazi vengono considerati equivalenti a una tabulazione ma è possibile specificare un valore differente adoperando l'argomento -t.