Il comando ‘sed’ permette di manipolare, filtrare, trasformare testi o flussi di testi; con flussi di testi intendo che può lavorare anche su dati che gli arrivano un po’ per volta. In modo predefinito elabora i file di testo riga per riga.

sed è tipico degli ambienti GNU/Linux e Unix in generale. Prerequisito di questa guida è la conoscenza almeno basilare delle espressioni regolari, se ancora non lo avete letto o non le conoscete leggetevi prima questo articolo. Un esempio semplice di utilizzo di sed lo trovate invece qui.

Questa introduzione è abbastanza completa ma non tratta ancora tutto perché le mie conoscenze di sed non sono ancora a livelli “guru” :).

Aggiornerò la guida quando avrò più conoscenze di sed! Potete comunque trovare già moltissime spiegazioni ed esempi adesso.

|| Versione guida: 1.1 ||

############

** in preparazione: script con sed, molto più potenti del semplice utilizzo a linea di comando **

10/12/2007 – v. 1.1

  • aggiunto il comando “transliterate”, per sostituire certi caratteri con altri, ai comandi spiegati ( y/prima/dopo/ )

############


le opzioni principali (per le altre guardate il manuale):

  • -n o --quiet o --silent « inibisce la stampa di ciò che viene fatto (vedere gli esempi)
  • -e script o --expression[=script « specifica uno script tra gli apici (opzione già vista) direttamente sulla linea di comando. Più comandi vanno separati da un punto e virgola ‘;’
  • -i[SUFFISSO] o --in-place[=SUFFISSO] « richiede di modificare direttamente il file, se viene specificato un suffisso viene creato un file di backup. consiglio di porre attenzione quando utilizzate questa opzione
    es.
    sed -i # modifica senza creare un backup
    sed --in-place # come sopra
    sed -i.bak # creerà una copia del file aggiungendo alla fine .bak
    sed --in-place=.bak # stesso di sopra
  • -f script-file o --file=script-file « specifica un file di script

queste sono le opzioni del comando, ben poca cosa! Quel che più serve sono i comandi degli script! Io ve ne mostrerò solo alcuni, i pochi già utilizzati e poco altro, come al solito per tutti i comandi consultate il manuale (man sed)

In genere i comandi si distinguono in due gruppi: quelli che selezionano delle righe su cui lavorare e quelli che eseguono qualche operazione. Sed vuole che prima si selezionino le righe su cui lavorare e quindi gli si dica come lavorare su di esse! Se non viene specificato su quali righe lavorare sed opererà su tutte.

  • p « stampa ciò che stà elaborando, per comprendere il comando provate questi:
    sed -e '' vostro-file.txt # non fa nulla (ma stampa tutto il file)
    sed -n -e '' vostro-file.txt # non fa nulla e non stampa nulla (opzione -n)
    sed -e 'p' vostro-file.txt # stampa il file (ogni riga due volte come vedrete)
    sed -n -e 'p' vostro-file.txt # stampa il file una sola volta
    ora dovreste comprendere il significato dell’opzione -n, il modo migliore per capirlo è provare ad eseguire i comandi con e senza quest’opzione
  • p « stampa la riga (print)
  • /regex/p « elabora e stampa le sole righe corrispondenti alla regex
  • d « elimina la riga (usarlo senza l’opzione -n) – (delete)
  • /regex/d « elimina le righe che corrispondono alla regex
  • s/regex/sostituto/ « come già visto sostituisce il testo individuato dalla regex con quello che gli viene indicato; lo fà però solo la prima volta che lo incontra per ogni riga
    dove ho scritto “sostituto” potete fare in modo che venga inserita l’espressione trovata tramite la regex utilizzando la e-commerciale (&) (substitute)
  • g « “mantiene” la riga corrente, scusate se non spiego meglio ma non ho ancora usato abbastanza questo comando da capirlo a fondo 😀
  • s/regex/sostituto/g « come sopra ma non si ferma al primo testo individuato
  • y/prima/dopo/ « questo sostituisce i caratteri “prima” con i corrispondenti “dopo”
    es.:
    y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/ « trasforma tutti i caratteri minuscoli in caratteri maiuscoli. Il primo carattere nella prima parte (a) diventa il primo nella seconda (A)
  • 4 « corrisponde alla quarta riga
  • 3p « stampa la terza riga (usatelo con l’opzione -n altrimenti la terza riga verrà stampata due volte e il resto una sola volta)
  • inizio,fine « corrisponde a tutte le righe da ‘inizio’ a ‘fine’ (comprese)
    es.
    1,5d « le prime cinque righe vengono eliminate
    4,12p « le righe dalla 4 alla 12 vengono stampate
  • prima~passo « corrisponde a tutte le righe a partire dalla riga ‘prima’ e da quella ogni ‘passo’ righe, và usato assieme ad un comando
    es.
    1~2p « stampa tutte le righe dispari (parte dalla prima e poi ogni 2). Stesso risultato di quello che abbiamo fatto con awk
    2~2p « stampa tutte le righe pari (parte dalla seconda e poi ogni 2)
    5~3p « stampa le righe: “5, 8, 11, 14, …” (parte dalla quinta poi ogni 3)
    6~10d « elimina le righe: “6, 16, 26, …” (parte dalla sesta poi ogni 10)
  • /regex-inizio/,/regex-fine/p « stampa tutte le righe comprese tra la prima che soddisfa la ‘regex-inizio’ e una che soddisfa la ‘regex-fine’
  • 1~2s/Linux/GNU\/&/g « sostituisce la parola ‘Linux’ con ‘GNU/Linux’ solo nelle righe dispari (il primo comando seleziona le righe su cui agire, se ne può usare qualunque altro per questo scopo; compreso ‘/regex-inizio/,/regex-fine/’! Il secondo comando agisce su queste righe decidendo il da farsi…)
  • s:regex:sostituto:g « capita a volte di avere tanti caratteri ‘/’ da sostituire, digitare tutte le volte ‘\/‘ può essere frustrante! Il comando ‘s//‘ si può modificare per accettare altri caratteri come limitatori, in questo caso abbiamo scelto i due punti.
    es.
    s:/home/daniele:/home/andrea:g « questo comando sostituisce ‘/home/daniele’ con ‘/home/andrea’ in un file di testo

NOTA: ricordatevi che se usate dei caratteri jolly (*,+) per indicare una qualunque ripetizione di qualche carattere la regex cercherà la sequenza più lunga che riesce a trovare!! Per capire cosa questo comporta facciamo un esempio suppongendo di voler rimuovere i tag da un file html:

prendiamo questa sequenza:

Sono <b>davvero</b> soddisfatto di <i>Linux</i>!!!

verrebbe naturale usare quest’espressione regolare per rimuovere i tag:

s/<.*>//g « che significa: sostituisci con ‘nulla’ le sequenze che cominciano con ‘<‘, finiscono con ‘>’ e al loro interno hanno una sequenza di qualunque carattere….

Il risultato di questa espressione è il seguente:

Sono !!!

Ha tolto tutto quello che stà tra il primo ”! Evidentemente non è ciò che si voleva… per ovviare si utilizza una regex come questa:

s/<[^>]*>//g « che significa: sostituisci con ‘nulla’ le sequenze che cominciano con ‘<‘, finiscono con ‘>’ e al loro interno hanno una sequenza di qualunque carattere che non sia un ‘>’…

Il risultato è:

Sono davvero soddisfatto di Linux!!!

Le potenzialità usando dei file di script sono anche maggiori! Vi lascio alcuni link di approfondimento ma sono sicuro che potete trovarne altri nel web…

Gentoo Wiki – Sed by examples

Esempi pratici sulla pagina ufficiale di sed

Tutto chiaro? Esercitatevi un po’ e sarà sempre più chiaro… 🙂