Shell Linux – Terza lezione

Testo, variabili e ricerca

echo, tr, column, grep e find
← Torna al modulo Linux

Il percorso delle lezioni

Dopo i file di testo e le wildcard, lavoriamo sul contenuto dei file: scriviamo testo, conserviamo valori in variabili, trasformiamo caratteri e cerchiamo righe o percorsi.

← Seconda lezione: file di testoQuarta lezione: permessi →

Preparare la cartella di lavoro

Usiamo la shell Bash e i comandi disponibili in una distribuzione GNU/Linux. Esegui gli esempi nello stesso terminale, nell’ordine indicato. Dalla seconda lezione riprendiamo la lettura dei file con cat e il reindirizzamento con >.

Comandi

mkdir -p ~/laboratorio_linux/lezione3
cd ~/laboratorio_linux/lezione3

I file della lezione vengono creati qui. Un comando riuscito non deve necessariamente stampare qualcosa: mkdir e cd, per esempio, normalmente non producono output. Se column non è installato, verifica con il docente il pacchetto previsto dalla distribuzione.

echo — Scrivere testo sul terminale

echo scrive gli argomenti sullo standard output e, normalmente, aggiunge un ritorno a capo.

Comandi

echo "Ciao Linux"

Output

Ciao Linux

In Bash, -n evita il ritorno a capo; -e interpreta sequenze come \n (nuova riga) e \t (tabulazione).

Comandi

echo -n "Classe: "
echo "3A"
echo -e "prima riga\nseconda riga"

Output

Classe: 3A
prima riga
seconda riga

Il comportamento delle opzioni di echo può cambiare tra shell. Qui usiamo il comando interno di Bash. Negli script che devono funzionare con shell diverse si preferisce spesso printf.

Scrivere in un file

Comandi

echo "Prima riga" > appunti.txt
echo "Seconda riga" >> appunti.txt
cat appunti.txt

Output

Prima riga
Seconda riga

> crea il file o ne sostituisce il contenuto; >> aggiunge testo in fondo. Non eseguire echo con > su un file che vuoi conservare senza prima controllarne il percorso.

Variabili — Memorizzare e riutilizzare un valore

Una variabile associa un nome a un valore. Nell’assegnazione non si mettono spazi intorno a =; per leggere il valore si antepone $ al nome.

Comandi

nome="Anna Rossi"
classe="3A"
echo "Studente: $nome; classe: $classe"

Output

Studente: Anna Rossi; classe: 3A

I nomi possono contenere lettere, cifre e underscore, ma non iniziano con una cifra. Maiuscole e minuscole sono diverse: nome e Nome indicano variabili distinte.

Virgolette doppie e apici singoli

Comandi

echo "$nome"
echo '$nome'

Output

Anna Rossi
$nome

Le virgolette doppie consentono l’espansione della variabile e mantengono insieme il valore, anche se contiene spazi. Gli apici singoli conservano il testo letterale. Usa normalmente "$variabile" quando passi un valore a un comando.

Variabili nei percorsi e nei nomi

Comandi

cartella="materiali di rete"
mkdir -p "$cartella"
echo "Appunti TCP/IP" > "$cartella/reti.txt"
echo "${classe}_registro.txt"

Output

3A_registro.txt

Le parentesi graffe delimitano il nome: in ${classe}_registro.txt la variabile è classe. Senza graffe la shell leggerebbe classe_registro come nome della variabile.

Queste assegnazioni valgono nella shell corrente. Per rendere una variabile disponibile ai nuovi processi avviati da quella shell si usa export nome; non serve per riutilizzarla negli esempi di questo terminale.

Reindirizzamenti e pipe — Collegare i comandi

< fa leggere lo standard input da un file. La pipe | collega lo standard output del comando a sinistra allo standard input di quello a destra.

Comandi

echo "ciao linux" | tr '[:lower:]' '[:upper:]'

Output

CIAO LINUX

Qui echo produce il testo e tr lo trasforma. L’operatore | non crea un file intermedio e, da solo, non inoltra lo standard error.

tr — Trasformare caratteri

tr legge dallo standard input. Può sostituire caratteri, eliminarli o comprimere ripetizioni; non sostituisce parole intere.

Comandi

echo "router;switch;server" | tr ';' ','
echo "PC-01" | tr -d '-'
echo "rete   locale" | tr -s ' '

Output

router,switch,server
PC01
rete locale
  • tr ';' ',' trasforma ogni punto e virgola in una virgola.
  • -d elimina i caratteri indicati.
  • -s riduce le sequenze ripetute dei caratteri indicati a un solo carattere.

Per leggere un file scrivi, per esempio, tr ';' ',' < dispositivi.txt. tr non accetta un nome di file come argomento di ingresso. Gli esempi di maiuscole/minuscole usano testo ASCII: non assumere che GNU tr gestisca tutte le lettere Unicode allo stesso modo.

Un file di dati per i prossimi esempi

Creiamo un elenco con tre campi separati da ;: nome, classe e voto. Le prime quattro righe sono scritte direttamente dalla shell.

Comandi

echo "nome;classe;voto" > studenti.txt
echo "Anna;3A;8" >> studenti.txt
echo "Luca;3B;6" >> studenti.txt
echo "Sara;3A;9" >> studenti.txt
cat studenti.txt

Output

nome;classe;voto
Anna;3A;8
Luca;3B;6
Sara;3A;9

I campi di questo esempio non contengono ; al loro interno. È un file delimitato semplice; i comandi seguenti non sono parser completi di CSV con campi tra virgolette.

column — Allineare i dati in una tabella

column -t dispone i campi in una tabella. Con -s ';' specifichiamo il separatore di ingresso.

Comandi

column -t -s ';' studenti.txt

Output

nome  classe  voto
Anna  3A      8
Luca  3B      6
Sara  3A      9

Il file originale non cambia: column stampa una versione allineata. Puoi salvare il risultato con un reindirizzamento.

Comandi

column -t -s ';' studenti.txt > studenti_tabella.txt

Senza -s, nella modalità -t i campi sono separati da spazi e tabulazioni. Gli spazi di allineamento nell’output possono variare con la versione del comando e il contenuto dei dati.

grep — Cercare righe nel contenuto dei file

grep seleziona le righe che corrispondono a un criterio di ricerca. La sintassi di base è grep 'modello' file.

Comandi

grep ';3A;' studenti.txt

Output

Anna;3A;8
Sara;3A;9

Con -n compare il numero della riga originale; -i ignora la differenza tra maiuscole e minuscole.

Comandi

grep -n -i 'anna' studenti.txt

Output

2:Anna;3A;8

Ricerca letterale ed espressioni regolari

Per impostazione predefinita grep interpreta il modello come un’espressione regolare. ^ indica l’inizio della riga e $ la fine. Con -F cerchi invece una stringa letterale.

Comandi

grep '^Sara;' studenti.txt
grep ';9$' studenti.txt
grep -F ';3A;' studenti.txt

Output

Sara;3A;9
Sara;3A;9
Anna;3A;8
Sara;3A;9

-v seleziona le righe che non corrispondono. Per togliere l’intestazione:

Comandi

grep -v '^nome;' studenti.txt

Output

Anna;3A;8
Luca;3B;6
Sara;3A;9

Una regex di grep è diversa dalle wildcard della shell: *.txt seleziona nomi di file; ^Sara; cerca testo nelle righe. Una ricerca senza risultati normalmente non stampa nulla.

find — Cercare file e directory

find percorre una directory e le sue sottodirectory. Seleziona gli elementi in base a nome, tipo e altri criteri. A differenza di grep, negli esempi qui sotto cerca percorsi, non righe di testo.

Comandi

find . -type f -name '*.txt'

Output

./appunti.txt
./materiali di rete/reti.txt
./studenti.txt
./studenti_tabella.txt

È l’insieme dei risultati atteso dopo gli esempi precedenti; l’ordine può cambiare. . è il punto di partenza, -type f limita la ricerca ai file normali e -name confronta il nome con una wildcard.

Il modello '*.txt' va tra apici: deve arrivare a find senza che la shell lo espanda prima.

Comandi

find . -maxdepth 1 -type f -name '*.txt'

Output

./appunti.txt
./studenti.txt
./studenti_tabella.txt

-maxdepth 1 limita la ricerca al punto di partenza e ai suoi figli diretti. Il file nella sottocartella non viene incluso. Con -type d selezioni invece le directory.

Comandi

find . -type d

Output

.
./materiali di rete

-name distingue maiuscole e minuscole; -iname ignora questa differenza. Per esempio: find . -type f -iname '*.txt'.

Combinare filtro, trasformazione e formattazione

Selezioniamo gli studenti della 3A e rendiamo leggibile il risultato:

Comandi

grep -F ';3A;' studenti.txt | column -t -s ';'

Output

Anna  3A  8
Sara  3A  9

Ora trasformiamo i separatori e salviamo un nuovo file:

Comandi

grep -F ';3A;' studenti.txt | tr ';' ',' > classe_3A.txt
cat classe_3A.txt

Output

Anna,3A,8
Sara,3A,9

Il risultato finale dipende dall’ordine: prima grep seleziona le righe usando il separatore originale, poi tr cambia i caratteri, infine > salva il testo.

Esercizi

  1. Assegna a materia il valore Sistemi e Reti e stampa Materia: Sistemi e Reti.
  2. Crea saluto.txt con una riga Ciao classe e aggiungi una seconda riga Oggi lavoriamo con Bash.
  3. Trasforma saluto.txt in maiuscolo e salva il risultato in saluto_maiuscolo.txt.
  4. Da studenti.txt seleziona la classe 3B e mostra i campi allineati.
  5. Mostra tutte le righe degli studenti, senza l’intestazione, in una tabella.
  6. Cerca i file .txt solo nella cartella corrente; poi ripeti la ricerca includendo le sottocartelle. Spiega quale opzione cambia.
Soluzioni

Comandi

materia="Sistemi e Reti"
echo "Materia: $materia"

echo "Ciao classe" > saluto.txt
echo "Oggi lavoriamo con Bash" >> saluto.txt
tr '[:lower:]' '[:upper:]' < saluto.txt > saluto_maiuscolo.txt

grep -F ';3B;' studenti.txt | column -t -s ';'
grep -v '^nome;' studenti.txt | column -t -s ';'

find . -maxdepth 1 -type f -name '*.txt'
find . -type f -name '*.txt'

Nella prima ricerca -maxdepth 1 esclude i file nelle sottocartelle. Nella seconda non c’è quel limite.

Manuali dei comandi

Nel terminale usa help echo per il comando interno di Bash e man tr, man column, man grep, man find per gli altri comandi.

↑ Torna su