[inizio] [indice generale] [precedente] [successivo] [indice analitico] [contributi]


184. SED: introduzione

SED è un programma in grado di eseguire delle trasformazioni elementari in un flusso di dati di ingresso, proveniente indifferentemente da un file o da una pipeline. Questo flusso di dati viene letto sequenzialmente e la sua trasformazione viene restituita attraverso lo standard output.

Il nome è l'abbreviazione di Stream Editor, che descrive istantaneamente il senso di questo programma: editor di flusso. Volendo usare altri termini, lo si potrebbe definire come un programma per la modifica sequenziale di un flusso di dati espressi in forma testuale.

Volendo vedere SED come una scatola nera, lo si può immaginare come un oggetto che ha due ingressi: un flusso di dati in ingresso, composto da uno o più file di testo concatenati assieme; un flusso di istruzioni in ingresso, che compone il programma dell'elaborazione da apportare ai dati; un flusso di dati in uscita che rappresenta il risultato dell'elaborazione.

               Direttive di elaborazione
                            |
                            |
                            V
                       +---------+
    dati in ingresso   |         |     dati in uscita
---------------------->|  S E D  |----------------->
                       |         | 
                       +---------+

Figura 184.1: Flussi di dati che interessano SED.

In linea di principio, SED non consente di indicare dei caratteri speciali nei suoi comandi attraverso delle sequenze di escape.

184.1 Avvio dell'eseguibile

SED è costituito in pratica dall'eseguibile `sed', il quale interpreta un programma scritto in un linguaggio apposito, che gli viene fornito come argomento della riga di comando, o in un file.

sed [<opzioni>] [<programma-di-elaborazione>] [<file>...]

Il testo del programma, o il nome del file che lo contiene, può essere indicato attraverso delle opzioni adatte, oppure, in loro mancanza, può essere indicato come primo degli argomenti che seguono le opzioni. Alla fine possono essere indicati i file da elaborare, e in loro mancanza si usa lo standard input.

Alcune opzioni

-e <istruzioni>

--expression=<istruzioni>

Questa opzione, che può essere utilizzata anche più volte, permette di specificare delle istruzioni SED che si aggiungono alle altre eventualmente già indicate.

-f <file-delle-istruzioni>

--file <file-delle-istruzioni>

Questa opzione permette di indicare un file contenente una serie di istruzioni SED. Anche questa opzione può essere usata più volte, e in pratica, ogni volta aggiunge istruzioni al programma globale.

-n | --quiet | --silent

In condizioni normali, alla fine di ogni ciclo, SED emette il contenuto di quello che viene definito come pattern space. In pratica, ogni riga letta ed elaborata viene emessa attraverso lo standard output senza bisogno di un comando apposito. Utilizzando questa opzione, si fa in modo di evitare questo comportamento, e in tal modo il programma di elaborazione interpretato da SED deve ordinare quando emettere ogni riga.

184.2 Logica di funzionamento

Il primo compito di SED, una volta avviato, è quello di raccogliere tutto ciò che deve andare a comporre il programma di elaborazione: può trattarsi di direttive fornite singolarmente attraverso l'opzione `-e' e di gruppi di direttive fornite all'interno di file appositi, indicati attraverso l'opzione `-f'. In particolare, SED si prende cura di mantenerne intatto l'ordine. Successivamente, concatena i dati in ingresso secondo la sequenza indicata dei file posti alla fine della riga di comando, oppure utilizza direttamente lo standard input.

Lo schema che appare nella figura 184.2 si avvicina all'idea del funzionamento di SED: il flusso in ingresso viene letto sequenzialmente, una riga alla volta; ogni volta la riga viene messa in un'area transitoria, nota come pattern space; viene confrontata la riga con ogni direttiva del programma di elaborazione, e se nessuna di queste direttive coincide, la riga non viene elaborata, e si compie semplicemente l'azione predefinita prima di passare al prossimo ciclo di lettura. Se una o più direttive del programma di elaborazione corrispondono alla riga, vengono eseguite sequenzialmente le elaborazioni previste, e poi, alla fine, si passa comunque per l'esecuzione dell'azione predefinita.

        +--------------> Lettura di una riga
	|		         |
        |                        |
	|			 |
	|			 |
	|			 |
azione predefinita               |
	^			 V
	|	     La riga letta appartiene a
	|            uno dei gruppi selezionati?
	|	         |          |
	|	      NO |          | SÌ
	|<---------------'          |
        |                           V
        |                 Esegue le elaborazioni
	|		  previste per questa riga
        |                           |
        |                           |
        `<--------------------------'

Figura 184.2: Struttura semplificata del funzionamento di SED.

L'azione predefinita di SED è l'emissione del contenuto dell'area transitoria, per cui, se non venisse fornita alcuna direttiva a SED, si otterrebbe almeno la riemissione completa dello stesso file ricevuto in ingresso:

sed "" pippo.txt

L'esempio mostra proprio l'avvio dell'eseguibile `sed' allo scopo di interpretare una direttiva nulla, fornendo il file `pippo.txt' in ingresso. Il risultato è la riemissione del contenuto di questo file attraverso lo standard output.

Per impedire che questa azione si compia automaticamente, si utilizza l'opzione `-n' (ovvero `--quiet' o `--silent'). In questo modo, è compito delle direttive del programma di elaborazione il richiedere espressamente l'emissione della riga elaborata.

SED dispone di due aree transitorie per le elaborazioni: una che contiene la riga letta, ed è già stata indicata; l'altra, definita come hold space, viene gestita eventualmente attraverso le direttive del programma di elaborazione interpretato da SED. L'utilizzo di questa seconda area di memoria non viene mostrato in questo capitolo.

Dal momento che SED è un programma storico dei sistemi Unix, è bene tenere presente le limitazioni che potrebbe avere in questo o quel sistema. In particolare, qualche realizzazione di SED potrebbe porre un limite alla dimensione delle righe. Questo fatto va tenuto presente quando si vogliono realizzare dei programmi «portabili», ovvero, da usare su piattaforme diverse, con sistemi operativi diversi.

POSIX GNU Descrizione
\ \ Escape.
^ ^ Inizio riga.
$ $ Fine riga.
\| Alternativa.
\(   \) Raggruppamento.
\n \n Riferimento.
x* x* Zero o più caratteri qualsiasi.
x\? Un carattere qualsiasi.
x\+ Uno o più caratteri qualsiasi
x\{n\} x\{n\} Esattamente n volte x.
x\{n,\} x\{n,\} Almeno n volte x.
x\{n,m\} x\{n,m\} Da n a m volte x.
x\{,m\} x\{,m\} Da zero a m volte x.
[   ] [   ] Elenco.
   xy...    xy...    Sequenze.
   x-y    x-y    Intervalli.
   [.   .]    Elementi di collazione.
   [=   =]    Caratteri equivalenti.
   [:   :]    [:   :]    Classi di caratteri.

Tabella 184.1: Riepilogo delle espressioni regolari di SED (BRE).

184.3 Script e direttive multiple

Di solito, si vede utilizzare SED con direttive fornite direttamente attraverso la stessa riga di comando. Volendo realizzare un programmino un po' più complesso, si potrebbe scrivere direttamente uno script che deve essere interpretato direttamente da SED. Per farlo, occorre iniziare il file in questione con una delle due intestazioni seguenti:

#!/bin/sed -f

#!/bin/sed -nf

Nel primo caso, si fa in modo di fornire all'eseguibile `sed' (Si suppone che si trovi nella directory `/bin/') l'opzione `-f', in modo che il file stesso venga inteso correttamente come un programma di elaborazione; nel secondo, oltre a questo, viene aggiunta l'opzione `-n', con la quale si inibisce l'emissione predefinita delle righe dopo ogni ciclo di elaborazione. *1*

Per quanto riguarda le direttive contenute nei file, queste utilizzano una riga per ognuna, dove le righe bianche o vuote vengono ignorate, assieme ai commenti che iniziano con il simbolo `#':

<direttiva-di-elaborazione>
<direttiva-di-elaborazione>
...

Le direttive fornite attraverso la riga di comando sono solitamente istruzioni singole, e volendo aggiungerne delle altre, si utilizzano più opzioni `-e':

sed -e <direttiva-di-elaborazione> [-e <direttiva-di-elaborazione>]... <file-in-ingresso>...

Tuttavia, di solito è possibile indicare più direttive con una sola opzione `-e', separandole con un punto e virgola:

sed -e <direttiva-di-elaborazione>[;<direttiva-di-elaborazione>]... <file-in-ingresso>...

L'uso di più direttive nella riga di comando, con o senza il punto e virgola, è sconsigliabile in generale, dal momento che dovendo scrivere un programma di elaborazione complesso è preferibile usare un file, trasformandolo eventualmente in uno script come è stato mostrato all'inizio di questa sezione.

184.4 Direttive

Ogni direttiva di un programma di elaborazione SED fa riferimento, esplicitamente o implicitamente, a un gruppo di righe, identificate in qualche modo, a cui vengono applicati dei comandi.

[<selezione-righe>]<comando>

Il modello sintattico mostra l'indicazione di un comando dopo la selezione delle righe; questo comando può essere un raggruppamento di comandi, indicato all'interno di parentesi graffe.

184.4.1 Selezione delle righe

La selezione delle righe per una direttiva SED è il primo elemento importante per queste. La mancanza dell'indicazione esplicita di questa selezione rappresenta implicitamente la selezione di tutte le righe.

È importante osservare che le righe possono essere indicate anche attraverso la corrispondenza con un'espressione regolare, e questo non deve essere confuso con i comandi che a loro volta possono avere a che fare con altre espressioni regolari.

Inoltre, è necessario ricordare che SED numera le righe a partire dalla prima del primo file, e continua fino alla fine dell'ultimo file, senza interrompere la numerazione.

184.4.2 Comandi comuni

Come accennato, ogni direttiva si compone di una selezione di righe, in modo esplicito o implicito, e di un comando, ovvero di un raggruppamento di comandi racchiuso tra parentesi graffe. Vengono elencati di seguito i comandi più comuni.

Alcuni comandi che qui non vengono descritti, richiedono una scomposizione in più righe, indicando la continuazione attraverso il simbolo `\'. Dal momento che questi comandi non vengono mostrati, quello che si vuole far notare è che la barra obliqua inversa come simbolo si continuazione ha un significato speciale in SED, e non va usata a meno di sapere esattamente quale sia il suo significato.

184.5 Esempi

In questa sezione vengono mostrati alcuni esempi dell'utilizzo di SED. A seconda dei casi, e dell'opportunità della cosa, si fa riferimento a direttive fornite nella riga di comando (con o senza l'opzione `-e'), oppure a uno script vero e proprio.

Elaborazioni banali

sed "" prova.txt

Legge il file `prova.txt' e lo riemette tale e quale, dal momento che non è stato specificata alcuna direttiva per il programma di elaborazione.

sed -n 'p' prova.txt

Si ottiene lo stesso risultato dell'esempio precedente, perché prima viene usata l'opzione `-n' con cui si inibisce la riemissione predefinita delle righe lette, ma poi si specifica una direttiva contenente il comando `p' applicato a tutte le righe del flusso in ingresso.

Selezione delle righe

sed -n '1,10/p' prova.txt

Emette solo le prime 10 righe del file.

sed '/.\{81,\}/d' prova.txt

Elimina le righe più lunghe di 80 caratteri.

sed '/^$/d' prova.txt

Elimina tutte le righe vuote.

sed '/^---INIZIO---$/,/^---FINE---$/d' prova.txt

Elimina tutte le righe comprese negli intervalli delimitati da righe contenenti esclusivamente la stringa `---INIZIO---' e `---FINE---'.

sed -n '/^---INIZIO---$/,/^---FINE---$/p' prova.txt

Emette tutte le righe comprese negli intervalli delimitati da righe contenenti esclusivamente la stringa `---INIZIO---' e `---FINE---'.

Sostituzione del contenuto delle righe

sed 's/andato/venuto/' prova.txt

Sostituisce in ogni riga la prima occorrenza della stringhe «andato» con la stringa «venuto».

sed 's/andato/venuto/g' prova.txt

Sostituisce tutte le occorrenze della stringa «andato» con la stringa «venuto».

sed 's/^/    /' prova.txt

Aggiunge quattro spazi all'inizio di ogni riga del file.

sed 's/\(.*\):\(.*\):\(.*\):\(.*\):\(.*\):\(.*\):\(.*\)/\1:\3/' /etc/passwd

Seleziona solo il primo e il terzo campo del file `/etc/passwd'; in pratica, preleva il nominativo e il numero UID.

Raggruppamenti

#!/bin/sed -nf
{
p
w registro
}

L'esempio mostra l'unione di due comandi riferiti allo stesso gruppo di righe (tutte). Lo scopo è quello di emettere le righe attraverso lo standard output e di annotarle anche in un file denominato `registro'.

Si osservi il fatto che la parentesi graffa di chiusura deve essere indicata da sola, come si vede nell'esempio, e di conseguenza può essere opportuno fare altrettanto per quella di apertura.

sed -n -e 'p' -e 'w registro' prova.txt

Questo esempio fa la stessa cosa di quello precedente, con la differenza che i comandi sono stati separati in due direttive riferite allo stesso gruppo di righe, e inoltre si elaborano le righe del file `prova.txt'.

184.6 Riferimenti

---------------------------

Appunti Linux 2000.04.12 --- Copyright © 1997-2000 Daniele Giacomini --  daniele @ pluto.linux.it


1.) È bene osservare che in uno script del genere non è possibile fare riferimento alle variabili di ambiente.


[inizio] [indice generale] [precedente] [successivo] [indice analitico] [contributi]