tr è un comodissimo comando per tradurre stringhe in altre stringhe, cioè per manipolarle carattere per carattere. In questo articolo vediamo la logica di base e gli usi più frequenti, in modo che possiate poi affrontare anche i casi più complessi.
La logica
tr prende in input una stringa o comunque un testo, che può provenire dallo standard input o da una pipe. La sinossi è:
tr [opzioni] SET1 [SET2]
Le opzioni influenzano il comportamento di tr; i due set servono a dire cosa trasformare (SET1) e in cosa (SET2).
Minuscole in maiuscole
Il primo esempio serve a capire cosa sono SET1 e SET2. Spariamo una stringa dentro tr con echo e trasformiamo tutte le lettere dalla a alla z nelle corrispondenti maiuscole:
echo "ciao mondo" | tr 'a-z' 'A-Z'
Ogni carattere del primo set viene tradotto nel carattere corrispondente del secondo.
Cancellare caratteri: -d
L’opzione -d cancella i caratteri presenti nel set. Ho una stringa con il PIN, e voglio togliere tutti i numeri:
echo "il mio PIN è 12345" | tr -d '0-9'
Il PIN è scomparso: abbiamo chiesto di eliminare tutti i caratteri compresi tra 0 e 9. Senza -d, la stessa chiamata con due set sostituisce invece di cancellare. Qui sostituiamo ogni cifra con un asterisco:
echo "il mio PIN è 12345" | tr '0-9' '*'
(Sì, la combinazione 12345 è quella di una famosa valigia.)
Ridurre le ripetizioni: -s
Un altro uso frequente è ridurre a uno le sequenze di caratteri uguali. Se una stringa contiene molti spazi di fila, l’opzione -s (squeeze) li riduce a uno solo:
echo "troppi spazi qui" | tr -s ' '
Il complemento: -C
L’opzione -c prende il complemento di un set, cioè tutti i caratteri che non ci sono. Se vogliamo eliminare da una stringa tutto ciò che non è un numero, invece di elencare tutti gli altri caratteri diciamo semplicemente: cancella il complemento di 0-9.
echo "il mio PIN è 12345" | tr -cd '0-9'
Il risultato è 12345, ma senza a capo: abbiamo eliminato anche il newline, e il prompt compare subito dopo i numeri. Per salvarlo, aggiungiamo \n alla lista dei caratteri da non cancellare:
echo "il mio PIN è 12345" | tr -cd '0-9\n'
Spazi in tabulazioni
Si può anche trasformare gli spazi in tabulazioni (o viceversa). Qui ogni spazio fra le parole diventa un carattere di tabulazione:
echo "una stringa di parole" | tr ' ' '\t'
Modalità interattiva
Finora abbiamo usato tr con una pipe. Se non gli passiamo niente, legge dallo standard input: scriviamo noi, lui risponde. Sostituiamo con un asterisco le lettere a, b e c:
tr 'abc' '*'
Premiamo invio, scriviamo “ciao mondo” e tr risponde con la stringa tradotta: la c e la a di ciao sono diventate asterischi. Si esce con Ctrl+C.
SET1 e SET2
Ogni carattere di SET1 viene tradotto nel carattere corrispondente di SET2. Con due set della stessa lunghezza, in modalità interattiva, traduciamo a, b e c rispettivamente in x, y e z:
tr 'abc' 'xyz'
Scrivendo “ciao mondo” otteniamo “zixo mondo”: la c diventa z e la a diventa x, mentre la b non c’è. Se SET2 è più corto di SET1, l’ultimo carattere di SET2 viene usato a oltranza. Traduciamo a, b, c, d con x, y:
tr 'abcd' 'xy'
La a diventa x, e tutte le altre lettere di SET1 diventano y. È molto più chiaro da fare che da dire.
Tabella di riferimento
La scheda che usavo nel video, con struttura del comando, opzioni e sequenze.
Opzioni:
- -c considera i caratteri non presenti in SET1
- -C come sopra, ma tratta i caratteri come valori in byte
- -d cancella i caratteri presenti in SET1
- -s riduce a uno le sequenze di caratteri uguali presenti in SET1
- -t tronca SET1 alla lunghezza di SET2
- -u forza la non bufferizzazione dell’output
Sequenze:
- \NNN il carattere con valore ottale NNN
- \\ il carattere backslash
- \a il carattere “beep” udibile
- \b il carattere backspace
- \f il carattere di avanzamento carta
- \n il carattere di newline
- \r il carattere di andata a capo
- \t il carattere di tabulazione orizzontale
- \v il carattere di tabulazione verticale
- C1-C2 tutti i caratteri da C1 a C2
- [C*] copia C* nel SET2 per la lunghezza di SET1
- [C*REPEAT] ripete copie di C
- [:alnum:] qualsiasi carattere alfanumerico
- [:alpha:] qualsiasi carattere alfabetico
- [:blank:] qualsiasi spazio bianco orizzontale
- [:cntrl:] qualsiasi carattere di controllo
- [:digit:] qualsiasi numero
- [:graph:] qualsiasi carattere stampabile che non sia uno spazio
- [:lower:] qualsiasi carattere alfabetico minuscolo
- [:print:] qualsiasi carattere stampabile spazi inclusi
- [:punct:] qualsiasi segno di interpunzione
- [:space:] qualsiasi spazio orizzontale o verticale
- [:upper:] qualsiasi carattere alfabetico maiuscolo
- [:xdigit:] qualsiasi cifra esadecimale
- [=C=] qualsiasi carattere equivalente a C
Ad esempio, le classi di caratteri sono un modo più portabile di scrivere le maiuscole:
echo "ciao mondo" | tr '[:lower:]' '[:upper:]'
Per finire
tr è un comando di una potenza esagerata e comodissimo nella manipolazione di stringhe da riga di comando. Esercitatevi, giocateci, fatevi le vostre prove: vi sarà utile in un’infinità di casi.
Link e risorse
- il video su YouTube
- esempi e comandi della puntata su GitHub
- tr(1), pagina di manuale — il manuale completo
- tr su Wikipedia — in italiano
- tr (Unix), approfondimento — in inglese, con più esempi
Sostieni il canale
PER SOSTENERE IL CANALE BASTANO UN LIKE E UN’ISCRIZIONE!
questi link sono affiliati Amazon, acquistando i libri che ti consiglio sostieni il canale!
