GNU/Linux: sostituire il testo con tr

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

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!