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’opzionep
« stampa la riga (print)/regex/p
« elabora e stampa le sole righe corrispondenti alla regexd
« elimina la riga (usarlo senza l’opzione -n) – (delete)/regex/d
« elimina le righe che corrispondono alla regexs/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 riga3p
« 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 stampateprima~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…
Esempi pratici sulla pagina ufficiale di sed
Tutto chiaro? Esercitatevi un po’ e sarà sempre più chiaro… 🙂
21 gennaio, 2011 at 11:37
Ma scusa come scrivi? “conoscienza” , “giolli”.
23 gennaio, 2011 at 13:13
Scrivo a getto e mi preoccupo di più del contenuto che della forma.
Se questa fosse una testata giornalistica o un documento ufficiale curerei anche la forma
Grazie della segnalazione, provvedo a correggere
14 dicembre, 2009 at 14:54
Prima di tutti complimenti per la guida… mi è stat veramente utile. Seconda cosa volevo chiederti (visto che non ho trovato niente con google) e è possibile effettuare una sorta di copia incolla… Nel senso, se ho due parole “pippo pluto”, è possibile modificarle in “pluto pippo”?
Grazie mille
15 dicembre, 2009 at 0:14
ciò che vuoi fare si può ottenere con il grouping.
sed ‘s/\(pippo\) \(pluto\)/\2 \1/’
ovviamente al posto di pippo / pluto ci devi mettere delle regular expression…
perché se volevi semplicemente sostituire “pippo pluto” con “pluto pippo” ti bastava un:
sed ‘s/pippo pluto/pluto pippo/’
ma le regular expression centrano poco 🙂
10 novembre, 2009 at 10:08
sei un mito
10 marzo, 2008 at 17:16
[…] però diventando mastodontico! Quindi qui dentro vi linkero gli articoli che introducono regexp, sed e […]
19 dicembre, 2007 at 2:57
@Peppe
se ho ben capito vuoi che ti venga restituita la directory senza il file giusto?
non ti serve sed per questo
c’è un comando:
dirname
che fa quello che vuoi
e il suo duale: basename che lascia il solo nome del file o rimuove l’estensione
con sed puoi ottenere la stessa cosa di dirname così:
sed ‘s:[^/]*$::’
ho usato i due punti invece della / per l’espressione
praticamente [^/]*$ va a beccare l’ultima sequenza di caratteri che non contiene la /
e con la sostituzione la rimuove
19 dicembre, 2007 at 1:17
Ciao! grazie per la guida ma ho un dubbio: ho una stringa del tipo “/home/peppe/file”. Voglio manipolare questa stringa con sed affinchè mi venga restituito solo “/home/peppe”. Come faccio? grazie
4 dicembre, 2007 at 13:49
@Stemby
lol 😀
vedi che a quell’ora è meglio andare a dormire? 😛
4 dicembre, 2007 at 12:41
Cacchio, sei messo peggio di me! (o forse ora ti trovi in Asia?) 😉 Ovviamente mi riferisco all’ora della tua risposta!
Se guardi bene, nel comando lì sopra ti ho indicato tutte e due le correzioni: manca ancora da sistemare
6~10 –> 6~10d
Ciao!
4 dicembre, 2007 at 2:32
@Stemby
grazie..
si.. in realtà non sono complicate…
ma come tutte le cose si imparano meglio provando!
per questo vi ho consigliato di crearvi un testo e poi con quei 2 comandini (sed blabla) testare voi stessi…
4 dicembre, 2007 at 2:18
2 piccola sviste:
sed -e ‘s/s\/regex\/sostituto\/ « come già visto sostituisce una il testo individuato dalla regex con quello indicato/s\/regex\/sostituto\/ « come già visto sostituisce il testo individuato dalla regex con quello indicato/’ prova | sed -e ‘s/6~10 « elimina le righe: “6, 16, 26, …” (parte dalla sesta poi ogni 10)/6~10d « elimina le righe: “6, 16, 26, …” (parte dalla sesta poi ogni 10)/’ > prova.ok
😉 Scusa se ne ho approfittato per fare un po’ di pratica 🙂
Davvero complimenti! Alcune cose non sono proprio intuitive: credo che si debba anche andare un po’ “per tentativi”.
Notte.
2 dicembre, 2007 at 20:12
[…] sed: programma per manipolare e filtrare flussi di testi! « L’importante è avere un tit… ha detto, […]