Stream Editor - Stringhe

Comando sostitutivo

Le operazioni di sostituzione del testo come "trova e sostituisci" sono comuni in qualsiasi editor di testo. In questa sezione, illustriamo come SED esegue la sostituzione del testo. Di seguito è riportata la sintassi del comando di sostituzione.

[address1[,address2]]s/pattern/replacement/[flags]

Qui, address1 e address2sono rispettivamente gli indirizzi iniziale e finale, che possono essere numeri di riga o stringhe di pattern. Entrambi questi indirizzi sono parametri opzionali. Il modello è il testo che vogliamo sostituire con la stringa di sostituzione. Inoltre, possiamo specificare flag opzionali con il SED.

Nel file books.txt, abbiamo usato la virgola (,) per separare ogni colonna. Usiamo la barra verticale (|) per separare ogni colonna. A tale scopo, sostituire la virgola (,) con la barra verticale (|).

[jerry]$ sed 's/,/ | /' books.txt

Eseguendo il codice sopra, ottieni 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

Se osservi attentamente, solo la prima virgola viene sostituita e la seconda rimane così com'è. Perché? Non appena il pattern corrisponde, SED lo sostituisce con la stringa di sostituzione e passa alla riga successiva. Per impostazione predefinita, sostituisce solo la prima occorrenza. Per sostituire tutte le occorrenze, utilizzare il flag globale (g) con SED come segue:

[jerry]$ sed 's/,/ | /g' books.txt

Eseguendo il codice sopra, ottieni 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

Ora tutte le occorrenze di virgole (,) vengono sostituite con una barra verticale (|).

Possiamo istruire il SED ad eseguire la sostituzione del testo solo quando una corrispondenza di pattern riesce. L'esempio seguente sostituisce la virgola (,) con la barra verticale (|) solo quando una riga contiene il motivo The Pilgrimage.

[jerry]$ sed '/The Pilgrimage/ s/,/ | /g' books.txt

Eseguendo il codice sopra, ottieni 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

Oltre a ciò, SED può sostituire un'occorrenza specifica del modello. Sostituiamo solo la seconda istanza di virgola (,) con barra verticale (|).

[jerry]$ sed 's/,/ | /2' books.txt

Eseguendo il codice sopra, ottieni 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

Nell'esempio sopra, il numero alla fine del comando SED (o al posto della bandiera) implica la seconda occorrenza.

SED fornisce una caratteristica interessante. Dopo aver eseguito la sostituzione, SED fornisce un'opzione per mostrare solo le righe modificate. A tal fine, SED utilizza l'estensionepbandiera che si riferisce alla stampa. Il seguente esempio elenca solo le righe modificate.

[jerry]$ sed -n 's/Paulo Coelho/PAULO COELHO/p' books.txt

Eseguendo il codice sopra, ottieni il seguente risultato:

3) The Alchemist, PAULO COELHO, 197 
5) The Pilgrimage, PAULO COELHO, 288

Possiamo anche memorizzare le righe modificate in un altro file. Per ottenere questo risultato, usa ilwbandiera. L'esempio seguente mostra come farlo.

[jerry]$ sed -n 's/Paulo Coelho/PAULO COELHO/w junk.txt' books.txt

Abbiamo usato lo stesso comando SED. Cerchiamo di verificare il contenuto del filejunk.txt file.

[jerry]$ cat junk.txt

Eseguendo il codice sopra, ottieni il seguente risultato:

3) The Alchemist, PAULO COELHO, 197 
5) The Pilgrimage, PAULO COELHO, 288

Per eseguire la sostituzione senza distinzione tra maiuscole e minuscole, utilizzare il flag i che implica ignorare le maiuscole. L'esempio seguente esegue la sostituzione senza distinzione tra maiuscole e minuscole.

[jerry]$ sed  -n 's/pAuLo CoElHo/PAULO COELHO/pi' books.txt

Eseguendo il codice sopra, ottieni il seguente risultato:

3) The Alchemist, PAULO COELHO, 197 
5) The Pilgrimage, PAULO COELHO, 288

Finora, abbiamo usato solo il carattere foreslash (/) come delimitatore, ma possiamo anche usare la barra verticale (|), il segno (@), l'accento circonflesso (^), il punto esclamativo (!) Come delimitatore. L'esempio seguente mostra come utilizzare altri caratteri come delimitatori.

Supponiamo che sia necessario sostituire il percorso /bin/sed con /home/jerry/src/sed/sed-4.2.2/sed. Quindi, il tuo comando SED ha questo aspetto:

[jerry]$ echo "/bin/sed" | sed 's/\/bin\/sed/\/home\/jerry\/src\/sed\/sed-4.2.2\/sed/'

Eseguendo il codice sopra, ottieni il seguente risultato:

/home/jerry/src/sed/sed-4.2.2/sed

Possiamo rendere questo comando più leggibile e facile da capire. Usiamo la barra verticale (|) come delimitatore e vediamo il risultato.

[jerry]$ echo "/bin/sed" | sed 's|/bin/sed|/home/jerry/src/sed/sed-4.2.2/sed|'

Eseguendo il codice sopra, ottieni il seguente risultato:

/home/jerry/src/sed/sed-4.2.2/sed

Infatti! Abbiamo ottenuto lo stesso risultato e la sintassi è più leggibile. Allo stesso modo, possiamo usare il segno "a" (@) come delimitatore come segue:

[jerry]$ echo "/bin/sed" | sed 's@/bin/sed@/home/jerry/src/sed/sed-4.2.2/sed@'

Eseguendo il codice sopra, ottieni il seguente risultato:

/home/jerry/src/sed/sed-4.2.2/sed

In aggiunta a ciò, possiamo usare il cursore (^) come delimitatore.

[jerry]$ echo "/bin/sed" | sed 's^/bin/sed^/home/jerry/src/sed/sed-4.2.2/sed^'

Eseguendo il codice sopra, ottieni il seguente risultato:

/home/jerry/src/sed/sed-4.2.2/sed

Possiamo anche usare il punto esclamativo (!) Come delimitatore come segue:

[jerry]$ echo "/bin/sed" | sed 's!/bin/sed!/home/jerry/src/sed/sed-4.2.2/sed!'

Eseguendo il codice sopra, ottieni il seguente risultato:

/home/jerry/src/sed/sed-4.2.2/sed

Generalmente, la barra rovesciata (/) viene utilizzata come delimitatore ma a volte è più conveniente utilizzare altri delimitatori supportati con SED.

Creazione di una sottostringa

Abbiamo imparato il potente comando sostitutivo. Vediamo se riusciamo a trovare una sottostringa da un testo abbinato. Cerchiamo di capire come farlo con l'aiuto di un esempio.

Consideriamo il testo seguente:

[jerry]$ echo "Three One Two"

Supponiamo di doverlo disporre in una sequenza. Significa che dovrebbe stampare prima Uno, poi Due e infine Tre. Il seguente one-liner fa il necessario.

echo "Three One Two" | sed 's|\(\w\+\) \(\w\+\) \(\w\+\)|\2 \3 \1|'

Si noti che nell'esempio precedente, la barra verticale (|) viene utilizzata come delimitatore.

In SED, le sottostringhe possono essere specificate utilizzando un operatore di raggruppamento e deve essere preceduto da un carattere di escape, ovvero \( e \).

\wè un'espressione regolare che corrisponde a qualsiasi lettera, cifra o trattino basso e "+" viene utilizzato per trovare la corrispondenza con più di un carattere. In altre parole, l'espressione regolare\(\w\+\) corrisponde alla singola parola dalla stringa di input.

Nella stringa di input, ci sono tre parole separate da spazio, quindi ci sono threeespressioni regolari separate da spazio. La prima espressione regolare memorizza la prima parola, ovvero Tre, la seconda memorizza la parolaOnee il terzo memorizza la parola Two

Queste sottostringhe sono indicate da \N,dove N è il numero della sottostringa. Quindi,\2 stampa la seconda sottostringa, cioè One; \3 stampa la terza sottostringa, cioè Two; e \1 stampa la prima sottostringa, cioè Three

Separiamo queste parole con virgole (,) e modifichiamo l'espressione regolare di conseguenza.

[jerry]$ echo "Three,One,Two" | sed 's|\(\w\+\),\(\w\+\),\(\w\+\)|\2,\3,\1|'

Eseguendo il codice sopra, ottieni il seguente risultato:

One,Two,Three

Nota che ora c'è una virgola (,) invece dello spazio nell'espressione regolare.

Flag di sostituzione delle stringhe (solo GNU SED)

Nella sezione precedente, abbiamo visto alcuni esempi del comando di sostituzione. GNU SED fornisce alcune speciali sequenze di escape che possono essere usate nella stringa di sostituzione. Notare che questi flag di sostituzione delle stringhe sono specifici di GNU e potrebbero non funzionare con altre varianti di SED. Qui discuteremo i flag di sostituzione delle stringhe.

  • \ L: Quando \ L è specificato nella stringa di sostituzione, tratta tutti i caratteri rimanenti della parola dopo \ L come caratteri minuscoli. Ad esempio, i caratteri "ULO" vengono trattati come caratteri minuscoli.

[jerry]$ sed -n 's/Paulo/PA\LULO/p' books.txt

Eseguendo il codice sopra, ottieni il seguente risultato:

3) The Alchemist, PAulo Coelho, 197
5) The Pilgrimage, PAulo Coelho, 288
  • \ u: quando \ u è specificato nella stringa di sostituzione, tratta il carattere immediatamente dopo \ u come un carattere maiuscolo. Nell'esempio seguente, \ u viene utilizzato prima dei caratteri "a" e "o". Quindi SED tratta questi caratteri come lettere maiuscole.

[jerry]$ sed -n 's/Paulo/p\uaul\uo/p' books.txt

Eseguendo il codice sopra, ottieni il seguente risultato:

3) The Alchemist, pAulO Coelho, 197 
5) The Pilgrimage, pAulO Coelho, 288
  • \ U: Quando \ U è specificato nella stringa di sostituzione, tratta tutti i caratteri rimanenti della parola dopo \ U come caratteri maiuscoli.

[jerry]$ sed -n 's/Paulo/\Upaulo/p' books.txt

Eseguendo il codice sopra, ottieni il seguente risultato:

3) The Alchemist, PAULO Coelho, 197 
5) The Pilgrimage, PAULO Coelho, 288
  • \ E: questo flag dovrebbe essere usato con \ L o \ U. Arresta la conversione avviata dal flag \ L o \ U. Nell'esempio seguente, solo la prima parola viene sostituita con lettere maiuscole.

[jerry]$ sed -n 's/Paulo Coelho/\Upaulo \Ecoelho/p' books.txt

Eseguendo il codice sopra, ottieni il seguente risultato:

3) The Alchemist, PAULO coelho, 197 
5) The Pilgrimage, PAULO coelho, 288