sed è uno di quei comandi che si usano tutti i giorni senza accorgersene: serve principalmente a sostituire e manipolare il contenuto di file o, più in generale, di stringhe. In questo articolo vediamo la logica di base e gli usi più comuni, senza addentrarci nei casi più tecnici.
La sintassi
sed vuole due argomenti: il primo è lo script da eseguire (la sostituzione, o qualunque altra cosa vogliamo fare), il secondo è il file su cui lavorare. In alternativa può leggere dallo standard input e scrivere sullo standard output, quindi si concatena con pipe e redirezioni come gli altri comandi.
La sostituzione
Il primo esempio è il più semplice: sostituiamo la parola mondo con la parola Mario in una stringa passata in pipe. Lo script di sostituzione comincia con s, e usa lo slash come separatore: s, separatore, cosa cercare, separatore, con cosa sostituirlo, separatore.
echo "ciao mondo" | sed 's/mondo/Mario/'
Lo stesso esempio con un file. Scriviamo una stringa in mondo.txt e passiamo il file a sed:
echo "ciao mondo" > mondo.txt
sed 's/mondo/Mario/' mondo.txt
sed legge il contenuto del file, applica la sostituzione e scrive il risultato sullo standard output. Il file non viene toccato: se vogliamo salvare il risultato dobbiamo usare la redirezione dell’output (oppure l’opzione -i, che modifica il file sul posto, ma è un’altra storia).
Le occorrenze multiple
Aggiungiamo un paio di righe al file, in modo che la parola compaia più volte:
printf 'ciao mondo, mondo e mondo\nmondo mondo\n' > mondo.txt
printf 'mondo e ancora mondo\n' >> mondo.txt
cat mondo.txt
Se lanciamo di nuovo la sostituzione, vediamo che viene sostituita solo la prima occorrenza. Attenzione: la sostituzione si applica per riga, quindi senza altre indicazioni viene sostituita la prima occorrenza di ogni riga.
sed 's/mondo/Mario/' mondo.txt
Se mettiamo un numero in fondo, sed sostituisce l’occorrenza indicata, sempre per ogni riga. Qui la seconda:
sed 's/mondo/Mario/2' mondo.txt
E qui la terza. Se in una riga non c’è una terza occorrenza, quella riga resta com’è:
sed 's/mondo/Mario/3' mondo.txt
Per sostituire tutte le occorrenze si usa il flag g, che sta per global:
sed 's/mondo/Mario/g' mondo.txt
I due flag si combinano: un numero seguito da g significa “dalla N-esima occorrenza in avanti”. Per esempio, dalla seconda in poi:
sed 's/mondo/Mario/2g' mondo.txt
Scegliere le righe
Possiamo limitare la sostituzione a una riga specifica mettendo il numero di riga davanti allo script. Qui solo la seconda riga (e solo la prima occorrenza):
sed '2s/mondo/Mario/' mondo.txt
Le due cose si combinano: seconda riga, seconda occorrenza:
sed '2s/mondo/Mario/2' mondo.txt
Prima riga, tutte le occorrenze:
sed '1s/mondo/Mario/g' mondo.txt
Funzionano anche gli intervalli. Per sostituire solo nelle prime due righe:
sed '1,2s/mondo/Mario/' mondo.txt
Il flag p E l’opzione -N
Aggiungiamo altre due righe al file, una delle quali senza la parola mondo, e introduciamo il flag p:
printf 'una riga con la parola\n' >> mondo.txt
printf 'nessuna sostituzione qui\n' >> mondo.txt
cat mondo.txt
Il flag p fa una cosa che sembra strana: stampa una seconda volta le righe in cui è avvenuta una sostituzione. Le righe dove non è stata fatta nessuna sostituzione compaiono una volta sola.
sed 's/mondo/Mario/p' mondo.txt
Questo comportamento diventa utilissimo insieme all’opzione -n, che sopprime la stampa automatica: restano visibili solo le righe stampate esplicitamente, cioè quelle dove la sostituzione è avvenuta.
sed -n 's/mondo/Mario/p' mondo.txt
Naturalmente si combina con gli altri flag. Qui vediamo soltanto le righe che contenevano la parola mondo almeno tre volte, con le occorrenze dalla terza in poi sostituite:
sed -n 's/mondo/Mario/3gp' mondo.txt
Cancellare righe
Il comando d cancella righe dall’output. Il file non cambia, sono le righe a non essere stampate. Per eliminare la terza riga:
sed '3d' mondo.txt
Il simbolo del dollaro indica sempre l’ultima riga, anche se non sappiamo quante righe abbia il file. Per eliminare l’ultima:
sed '$d' mondo.txt
Il dollaro si può usare anche negli intervalli. Per eliminare dalla terza riga fino alla fine, in modo da vedere solo le prime due:
sed '3,$d' mondo.txt
d funziona anche con il pattern matching: per eliminare tutte le righe che contengono una certa parola.
sed '/mondo/d' mondo.txt
Oppure, al contrario, per eliminare quelle che contengono la parola parola:
sed '/parola/d' mondo.txt
Stampare solo certe righe
Il discorso funziona anche al contrario: con il comando p possiamo chiedere a sed di stampare un certo intervallo di righe. Senza -n le righe selezionate vengono stampate due volte, con -n le vediamo solo una volta:
sed '1,3p' mondo.txt
sed -n '1,3p' mondo.txt
Aggiungere righe
Con il comando a (append) si aggiunge una riga dopo quelle che corrispondono al pattern. Qui inseriamo una riga di esempio dopo ogni riga che contiene la parola parola:
sed '/parola/a riga di esempio' mondo.txt
Se invece la nuova riga deve andare prima di quella che corrisponde, si usa il comando i (insert):
sed '/parola/i riga di esempio' mondo.txt
Per finire
sed supporta una quantità enorme di opzioni e di comportamenti, anche molto complessi. Qui ho voluto presentarlo e mostrare gli usi più comuni: sostituire, selezionare, cancellare, stampare e aggiungere righe. Il consiglio è sempre lo stesso: aprite la vostra Linux box e giocateci, finché non vi diventa naturale. Se volete un approfondimento sui casi più complessi, fatemelo sapere.
Link e risorse
- il video su YouTube
- esempi e comandi della puntata su GitHub
- sed(1) in italiano — in italiano
- sed(1), pagina di manuale — il manuale completo
- Sed (Unix) — in italiano
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!
