Stream Editor: gestione dei pattern

Abbiamo già discusso l'uso di pattern e hold buffer. In questo capitolo, esploreremo di più sul loro utilizzo. Parliamo dincomando che stampa lo spazio del pattern. Verrà utilizzato insieme ad altri comandi. Di seguito è riportata la sintassi del comando then.

[address1[,address2]]n

Facciamo un esempio.

[jerry]$ sed 'n' books.txt

Quando il codice precedente viene eseguito, produrrà il seguente risultato:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

Il n comando stampa il contenuto del pattern buffer, cancella il pattern buffer, preleva la riga successiva nel pattern buffer e applica i comandi su di esso.

Consideriamo che ci sono tre comandi SED prima n e due comandi SED dopo n come segue:

Sed command #1 
Sed command #2 
Sed command #3 
n command 
Sed command #4 
Sed command #5

In questo caso, SED applica i primi tre comandi sul pattern buffer, cancella il pattern buffer, preleva la riga successiva nel pattern buffer e successivamente applica il quarto e il quinto comando su di esso. Questo è un concetto molto importante. Non andare avanti senza avere una chiara comprensione di questo.

Il buffer di blocco contiene i dati, ma i comandi SED non possono essere applicati direttamente al buffer di blocco. Quindi, dobbiamo portare i dati del buffer di blocco nel buffer del pattern. SED fornisce ilxcomando per scambiare il contenuto del pattern e trattenere i buffer. I seguenti comandi illustrano ilx comando.

Modifichiamo leggermente il file books.txt. Supponiamo che il file contenga i titoli dei libri seguiti dai nomi degli autori. Dopo la modifica, il file dovrebbe apparire così:

[jerry]$ cat books.txt

Eseguendo il codice sopra, ottieni il seguente risultato:

A Storm of Swords 
George R. R. Martin 
The Two Towers 
J. R. R. Tolkien 
The Alchemist 
Paulo Coelho 
The Fellowship of the Ring 
J. R. R. Tolkien 
The Pilgrimage 
Paulo Coelho 
A Game of Thrones 
George R. R. Martin

Scambiamo il contenuto dei due buffer. Ad esempio, il seguente esempio stampa solo i nomi degli autori.

[jerry]$ sed -n 'x;n;p' books.txt

Eseguendo il codice sopra, ottieni il seguente risultato:

George R. R. Martin 
J. R. R. Tolkien 
Paulo Coelho 
J. R. R. Tolkien 
Paulo Coelho 
George R. R. Martin

Facci capire come funziona questo comando.

  • Inizialmente, SED legge la prima riga, ovvero A Storm of Swords nel pattern buffer.

  • x Il comando sposta questa riga nel buffer di blocco.

  • n recupera la riga successiva, cioè George RR Martin nel pattern buffer.

  • Il controllo passa al comando seguito da n che stampa il contenuto del pattern buffer.

  • Il processo si ripete fino all'esaurimento del file.

Ora scambiamo il contenuto dei buffer prima della stampa. Indovina, cosa succede? Sì, stampa i titoli dei libri.

[jerry]$ sed -n 'x;n;x;p' books.txt

Eseguendo il codice sopra, ottieni il seguente risultato:

A Storm of Swords 
The Two Towers 
The Alchemist 
The Fellowship of the Ring 
The Pilgrimage 
A Game of Thrones

Il hil comando si occupa del buffer di attesa. Copia i dati dal pattern buffer al buffer hold. I dati esistenti dal buffer di blocco vengono sovrascritti. Nota che ilhcomando non sposta i dati, copia solo i dati. Quindi, i dati copiati rimangono come sono nel buffer del pattern. Di seguito è riportata la sintassi dih comando.

[address1[,address2]]h

Il comando seguente stampa solo i titoli dell'autore Paulo Coelho.

[jerry]$ sed -n '/Paulo/!h; /Paulo/{x;p}' books.txt

Eseguendo il codice sopra, ottieni il seguente risultato:

The Alchemist 
The Pilgrimage

Cerchiamo di capire come funziona il comando precedente. I contenuti di books.txt seguono un formato specifico. La prima riga è il titolo del libro seguito dall'autore del libro. Nel comando precedente, "!" viene utilizzato per invertire la condizione, ovvero la riga viene copiata nel buffer di blocco solo quando una corrispondenza del pattern non riesce. E le parentesi graffe {} vengono utilizzate per raggruppare più comandi SED

Nel primo passaggio del comando, SED legge la prima riga, cioè A Storm of Swords nel pattern buffer e controlla se contiene il pattern Paulo o no. Poiché la corrispondenza del pattern non riesce, copia questa riga nel buffer di blocco. Ora sia il pattern buffer che il hold buffer contengono la stessa riga, ovvero A Storm of Swords. Nella seconda fase, controlla se la riga contiene il pattern Paulo oppure no. Poiché il modello non corrisponde, non ha effetto.

Nel secondo passaggio, legge la riga successiva George RR Martin nel buffer del pattern e applica gli stessi passaggi. Per le tre righe successive, fa la stessa cosa. Alla fine del quinto passaggio, entrambi i buffer contengono The Alchemist. All'inizio del sesto passaggio, legge la linea Paulo Coelho e poiché lo schema corrisponde, non copia questa linea nel buffer di attesa. Quindi, il pattern buffer contiene Paulo Coelho e il hold buffer contiene The Alchemist.

Successivamente, controlla se il pattern buffer contiene il pattern Paulo. Quando il pattern match ha esito positivo, scambia il contenuto del pattern buffer con il buffer hold. Ora il pattern buffer contiene The Alchemist e il hold buffer contiene Paulo Coelho. Infine, stampa il contenuto del pattern buffer. Gli stessi passaggi vengono applicati al motivo The Pilgrimage.

Il hIl comando distrugge il contenuto precedente del buffer di blocco. Questo non è sempre accettabile, poiché a volte è necessario preservare i contenuti. A tal fine, SED fornisce ilHcomando che aggiunge il contenuto al buffer di blocco aggiungendo una nuova riga alla fine. L'unica differenza trah e HIl comando è che il primo sovrascrive i dati dal buffer di blocco, mentre il secondo aggiunge i dati al buffer di blocco. La sua sintassi è simile ah comando.

[address1[,address2]]H

Facciamo un altro esempio. Questa volta, invece di stampare solo i titoli dei libri, stampa anche i nomi dei loro autori. L'esempio seguente stampa i titoli dei libri seguiti dai nomi degli autori.

[jerry]$ sed -n '/Paulo/!h; /Paulo/{H;x;p}' books.txt

Eseguendo il codice sopra, ottieni il seguente risultato:

The Alchemist 
Paulo Coelho 
The Pilgrimage
Paulo Coelho

Abbiamo imparato come copiare / aggiungere il contenuto del pattern buffer per contenere il buffer. Possiamo eseguire anche la funzione inversa? Sì certamente! A tal fine, SED fornisce ilgcomando che copia i dati dal buffer hold al buffer pattern. Durante la copia, i dati esistenti dallo spazio del pattern vengono sovrascritti. Di seguito è riportata la sintassi dig comando.

[address1[,address2]]g

Consideriamo lo stesso esempio: la stampa di titoli di libri e dei loro autori. Questa volta stamperemo prima il nome dell'autore e nella riga successiva il titolo del libro corrispondente. Il comando seguente stampa il nome dell'autore Paulo Coelho, seguito dal titolo del libro.

[jerry]$ sed -n '/Paulo/!h; /Paulo/{p;g;p}' books.txt

Eseguendo il codice sopra, ottieni il seguente risultato:

Paulo Coelho 
The Alchemist 
Paulo Coelho 
The Pilgrimage

Il primo comando viene mantenuto così com'è. Alla fine del quinto passaggio, entrambi i buffer contengono The Alchemist. All'inizio del sesto passaggio, legge la linea Paulo Coelho e poiché lo schema corrisponde, non copia questa linea nel buffer di attesa. Quindi, lo spazio pattern contiene Paul Coelho e lo spazio hold contiene The Alchemist.

Successivamente, controlla se lo spazio del pattern contiene il pattern Paulo. Quando il pattern match ha successo, prima stampa il contenuto dello spazio pattern, cioè Paulo Coelho, poi copia il buffer hold nel pattern buffer. Quindi, sia il pattern che i buffer hold contengono The Alchemist. Infine, stampa il contenuto del pattern buffer. Gli stessi passaggi vengono applicati al motivo The Pilgrimage.

Allo stesso modo, possiamo aggiungere il contenuto dell'hold buffer al pattern buffer. SED fornisce ilG comando che aggiunge il contenuto al buffer del pattern aggiungendo una nuova riga alla fine.

[address1[,address2]]G

Prendiamo ora l'esempio precedente che stampa il nome dell'autore Paulo Coelhof seguito dal titolo del libro. Per ottenere lo stesso risultato, eseguire il seguente comando SED.

[jerry]$ sed -n '/Paulo/!h; /Paulo/{G;p}' books.txt

Eseguendo il codice sopra, ottieni il seguente risultato:

Paulo Coelho 
The Alchemist 
Paulo Coelho 
The Pilgrimage

Potete modificare l'esempio sopra per visualizzare i titoli dei libri seguiti dai loro autori? Semplice, basta scambiare il contenuto del buffer prima del fileG comando.

[jerry]$ sed -n '/Paulo/!h; /Paulo/{x;G;p}' books.txt

Eseguendo il codice sopra, ottieni il seguente risultato:

The Alchemist 
Paulo Coelho 
The Pilgrimage 
Paulo Coelho