Unix / Linux - Espressioni regolari con SED

In questo capitolo, discuteremo in dettaglio delle espressioni regolari con SED in Unix.

Un'espressione regolare è una stringa che può essere utilizzata per descrivere diverse sequenze di caratteri. Le espressioni regolari sono utilizzate da diversi comandi Unix, inclusoed, sed, awk, grepe, in misura più limitata, vi.

Qui SED sta per stream editor. Questo editor orientato al flusso è stato creato esclusivamente per l'esecuzione di script. Pertanto, tutto l'input che inserisci passa attraverso e va a STDOUT e non cambia il file di input.

Invocare sed

Prima di iniziare, assicurati di avere una copia locale di /etc/passwd file di testo con cui lavorare sed.

Come accennato in precedenza, sed può essere invocato inviando dati tramite una pipe come segue:

$ cat /etc/passwd | sed
Usage: sed [OPTION]... {script-other-script} [input-file]...

  -n, --quiet, --silent
                 suppress automatic printing of pattern space
  -e script, --expression = script
...............................

Il cat comando scarica il contenuto di /etc/passwd per sedattraverso il tubo nello spazio del modello di sed. Lo spazio del modello è il buffer di lavoro interno che sed utilizza per le sue operazioni.

La sintassi generale di sed

Di seguito è riportata la sintassi generale per sed -

/pattern/action

Qui, pattern è un'espressione regolare e actionè uno dei comandi riportati nella tabella seguente. Sepattern è omesso, action viene eseguita per ogni riga come abbiamo visto sopra.

Il carattere barra (/) che circonda il modello è obbligatorio perché vengono utilizzati come delimitatori.

Sr.No. Gamma e descrizione
1

p

Stampa la riga

2

d

Elimina la riga

3

s/pattern1/pattern2/

Sostituisce la prima occorrenza di pattern1 con pattern2

Eliminazione di tutte le righe con sed

Ora capiremo come eliminare tutte le righe con sed. Invoca nuovamente sed; ma ora si suppone che sed utilizzi l'estensioneediting command delete line, indicato dalla singola lettera d -

$ cat /etc/passwd | sed 'd'
$

Invece di invocare sed inviandogli un file tramite una pipe, si può istruire il sed a leggere i dati da un file, come nell'esempio seguente.

Il comando seguente fa esattamente lo stesso dell'esempio precedente, senza il comando cat -

$ sed -e 'd' /etc/passwd
$

Gli indirizzi sed

Il sed supporta anche gli indirizzi. Gli indirizzi sono posizioni particolari in un file o un intervallo in cui deve essere applicato un particolare comando di modifica. Quando il sed non trova indirizzi, esegue le sue operazioni su ogni riga del file.

Il comando seguente aggiunge un indirizzo di base al comando sed che hai utilizzato:

$ cat /etc/passwd | sed '1d' |more
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
$

Si noti che il numero 1 viene aggiunto prima del delete editcomando. Questo indica al sed di eseguire il comando di modifica sulla prima riga del file. In questo esempio, il sed cancellerà la prima riga di/etc/password e stampa il resto del file.

Gli intervalli di indirizzi sed

Ora capiremo come lavorare con the sed address ranges. Quindi cosa succede se si desidera rimuovere più di una riga da un file? È possibile specificare un intervallo di indirizzi con sed come segue:

$ cat /etc/passwd | sed '1, 5d' |more
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
$

Il comando precedente verrà applicato a tutte le righe a partire da 1 a 5. Ciò elimina le prime cinque righe.

Prova i seguenti intervalli di indirizzi:

Sr.No. Gamma e descrizione
1

'4,10d'

Linee a partire dal 4 ° fino al 10 ° vengono cancellati

2

'10,4d'

Viene eliminata solo la decima riga, perché sed non funziona in direzione inversa

3

'4,+5d'

Questo corrisponde alla riga 4 nel file, elimina quella riga, continua a eliminare le cinque righe successive, quindi cessa la sua eliminazione e stampa il resto

4

'2,5!d'

Questo cancella tutto tranne l'inizio dalla 2a alla 5a riga

5

'1~3d'

Ciò elimina la prima riga, passa sopra le tre righe successive e quindi elimina la quarta riga. Sed continua ad applicare questo modello fino alla fine del file.

6

'2~2d'

Questo dice a sed di eliminare la seconda riga, passare alla riga successiva, eliminare la riga successiva e ripetere fino a raggiungere la fine del file

7

'4,10p'

Vengono stampate le righe dal 4 ° al 10 °

8

'4,d'

Questo genera l'errore di sintassi

9

',10d'

Ciò genererebbe anche un errore di sintassi

Note - Durante l'utilizzo di p action, dovresti usare il -nopzione per evitare la ripetizione della stampa della riga. Controlla la differenza tra i seguenti due comandi:

$ cat /etc/passwd | sed -n '1,3p'
Check the above command without -n as follows −
$ cat /etc/passwd | sed '1,3p'

Il comando di sostituzione

Il comando di sostituzione, indicato da s, sostituirà qualsiasi stringa specificata con qualsiasi altra stringa specificata.

Per sostituire una stringa con un'altra, il sed deve avere le informazioni su dove finisce la prima stringa e inizia la stringa di sostituzione. Per questo, procediamo con il bookending delle due corde con la barra in avanti (/) personaggio.

Il comando seguente sostituisce la prima occorrenza su una riga della stringa root con lo spago amrood.

$ cat /etc/passwd | sed 's/root/amrood/'
amrood:x:0:0:root user:/root:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
..........................

È molto importante notare che sed sostituisce solo la prima occorrenza su una riga. Se la radice della stringa si verifica più di una volta su una riga, verrà sostituita solo la prima corrispondenza.

Affinché sed esegua una sostituzione globale, aggiungi la lettera g alla fine del comando come segue:

$ cat /etc/passwd | sed 's/root/amrood/g'
amrood:x:0:0:amrood user:/amrood:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
...........................

Bandiere di sostituzione

Ci sono una serie di altri flag utili che possono essere passati oltre a g flag e puoi specificarne più di uno alla volta.

Sr.No. Bandiera e descrizione
1

g

Sostituisce tutte le corrispondenze, non solo la prima

2

NUMBER

Sostituisce solo NUMERO ° incontro

3

p

Se è stata eseguita la sostituzione, stampa lo spazio del motivo

4

w FILENAME

Se è stata eseguita la sostituzione, scrive il risultato in FILENAME

5

I or i

Corrisponde senza distinzione tra maiuscole e minuscole

6

M or m

Oltre al normale comportamento dei caratteri speciali delle espressioni regolari ^ e $, questo flag fa sì che ^ corrisponda alla stringa vuota dopo una nuova riga e $ alla stringa vuota prima di una nuova riga

Utilizzo di un separatore di stringhe alternativo

Supponiamo di dover eseguire una sostituzione su una stringa che include il carattere barra. In questo caso, è possibile specificare un separatore diverso fornendo il carattere designato dopos.

$ cat /etc/passwd | sed 's:/root:/amrood:g'
amrood:x:0:0:amrood user:/amrood:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh

Nell'esempio sopra, abbiamo usato : come la delimiter invece di barra / perché stavamo cercando di cercare /root invece della semplice radice.

Sostituzione con spazio vuoto

Utilizzare una stringa di sostituzione vuota per eliminare la stringa radice dal file /etc/passwd file interamente -

$ cat /etc/passwd | sed 's/root//g'
:x:0:0::/:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh

Sostituzione dell'indirizzo

Se vuoi sostituire la stringa sh con lo spago quiet solo alla riga 10, è possibile specificarlo come segue:

$ cat /etc/passwd | sed '10s/sh/quiet/g'
root:x:0:0:root user:/root:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/quiet

Allo stesso modo, per eseguire una sostituzione dell'intervallo di indirizzi, potresti fare qualcosa di simile al seguente:

$ cat /etc/passwd | sed '1,5s/sh/quiet/g'
root:x:0:0:root user:/root:/bin/quiet
daemon:x:1:1:daemon:/usr/sbin:/bin/quiet
bin:x:2:2:bin:/bin:/bin/quiet
sys:x:3:3:sys:/dev:/bin/quiet
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh

Come puoi vedere dall'output, le prime cinque righe avevano la stringa sh cambiato in quiet, ma il resto delle righe è rimasto intatto.

Il comando di corrispondenza

Useresti il ​​file p opzione insieme a -n opzione per stampare tutte le righe corrispondenti come segue:

$ cat testing | sed -n '/root/p'
root:x:0:0:root user:/root:/bin/sh
[[email protected] amrood]# vi testing
root:x:0:0:root user:/root:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh

Utilizzo dell'espressione regolare

Durante la corrispondenza dei modelli, è possibile utilizzare l'espressione regolare che fornisce maggiore flessibilità.

Controlla il seguente esempio che corrisponde a tutte le righe che iniziano con daemon e quindi le elimina -

$ cat testing | sed '/^daemon/d'
root:x:0:0:root user:/root:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh

Di seguito è riportato l'esempio che cancella tutte le righe che terminano con sh -

$ cat testing | sed '/sh$/d'
sync:x:4:65534:sync:/bin:/bin/sync

La tabella seguente elenca quattro caratteri speciali molto utili nelle espressioni regolari.

Sr.No. Carattere e descrizione
1

^

Corrisponde all'inizio delle righe

2

$

Corrisponde alla fine delle righe

3

.

Corrisponde a qualsiasi singolo carattere

4

*

Corrisponde a zero o più occorrenze del carattere precedente

5

[chars]

Corrisponde a uno qualsiasi dei caratteri forniti in chars, dove chars è una sequenza di caratteri. È possibile utilizzare il carattere - per indicare un intervallo di caratteri.

Caratteri corrispondenti

Guarda alcune altre espressioni per dimostrare l'uso di metacharacters. Ad esempio, il seguente modello:

Sr.No. Espressione e descrizione
1

/a.c/

Corrisponde a righe che contengono stringhe come a+c, a-c, abc, match, e a3c

2

/a*c/

Corrisponde alle stesse stringhe insieme a stringhe come ace, yacc, e arctic

3

/[tT]he/

Corrisponde alla stringa The e the

4

/^$/

Corrisponde a righe vuote

5

/^.*$/

Corrisponde a un'intera riga qualunque essa sia

6

/ */

Corrisponde a uno o più spazi

7

/^$/

Partite blank Linee

La tabella seguente mostra alcuni set di caratteri usati di frequente:

Sr.No. Imposta e descrizione
1

[a-z]

Corrisponde a una singola lettera minuscola

2

[A-Z]

Corrisponde a una singola lettera maiuscola

3

[a-zA-Z]

Corrisponde a una singola lettera

4

[0-9]

Corrisponde a un singolo numero

5

[a-zA-Z0-9]

Corrisponde a una singola lettera o numero

Parole chiave della classe di caratteri

Alcune parole chiave speciali sono comunemente disponibili per regexps, in particolare le utilità GNU che impiegano regexps. Questi sono molto utili per le espressioni regolari sed in quanto semplificano le cose e migliorano la leggibilità.

Ad esempio, i personaggi a through z e i personaggi A through Z, costituiscono una di queste classi di caratteri con la parola chiave [[:alpha:]]

Utilizzando la parola chiave della classe di caratteri alfabetici, questo comando stampa solo quelle righe nel file /etc/syslog.conf file che iniziano con una lettera dell'alfabeto -

$ cat /etc/syslog.conf | sed -n '/^[[:alpha:]]/p'
authpriv.*                         /var/log/secure
mail.*                             -/var/log/maillog
cron.*                             /var/log/cron
uucp,news.crit                     /var/log/spooler
local7.*                           /var/log/boot.log

La tabella seguente è un elenco completo delle parole chiave delle classi di caratteri disponibili in GNU sed.

Sr.No. Classe e descrizione del carattere
1

[[:alnum:]]

Alfanumerico [az AZ 0-9]

2

[[:alpha:]]

Alfabetico [az AZ]

3

[[:blank:]]

Caratteri vuoti (spazi o tabulazioni)

4

[[:cntrl:]]

Caratteri di controllo

5

[[:digit:]]

Numeri [0-9]

6

[[:graph:]]

Eventuali caratteri visibili (esclusi gli spazi)

7

[[:lower:]]

Lettere minuscole [az]

8

[[:print:]]

Caratteri stampabili (caratteri non di controllo)

9

[[:punct:]]

Caratteri di punteggiatura

10

[[:space:]]

Spazio bianco

11

[[:upper:]]

Lettere maiuscole [AZ]

12

[[:xdigit:]]

Cifre esadecimali [0-9 af AF]

Riferimento Aampersand

Il sed metacharacter &rappresenta il contenuto del modello che è stato trovato. Ad esempio, supponi di avere un file chiamatophone.txt pieno di numeri di telefono, come i seguenti:

5555551212
5555551213
5555551214
6665551215
6665551216
7775551217

Vuoi creare il file area code(le prime tre cifre) circondate da parentesi per facilitare la lettura. Per fare ciò, puoi usare il carattere di sostituzione e commerciale -

$ sed -e 's/^[[:digit:]][[:digit:]][[:digit:]]/(&)/g' phone.txt
(555)5551212
(555)5551213
(555)5551214
(666)5551215

(666)5551216
(777)5551217

Qui nella parte del modello stai abbinando le prime 3 cifre e quindi usando & stai sostituendo quelle 3 cifre con il contorno parentheses.

Utilizzo di più comandi sed

È possibile utilizzare più comandi sed in un singolo comando sed come segue:

$ sed -e 'command1' -e 'command2' ... -e 'commandN' files

Qui command1 attraverso commandNsono comandi sed del tipo discusso in precedenza. Questi comandi vengono applicati a ciascuna delle righe nell'elenco di file fornito da file.

Utilizzando lo stesso meccanismo, possiamo scrivere l'esempio di numero di telefono sopra come segue:

$ sed -e 's/^[[:digit:]]\{3\}/(&)/g'  \ 
   -e 's/)[[:digit:]]\{3\}/&-/g' phone.txt 
(555)555-1212 
(555)555-1213 
(555)555-1214 
(666)555-1215 
(666)555-1216 
(777)555-1217

Note - Nell'esempio sopra, invece di ripetere la parola chiave della classe di caratteri [[:digit:]] tre volte, l'abbiamo sostituito con \{3\}, il che significa che l'espressione regolare precedente viene trovata tre volte. Abbiamo anche usato\ per dare un'interruzione di riga e questo deve essere rimosso prima che il comando venga eseguito.

Riferimenti indietro

Il ampersand metacharacterè utile, ma ancora più utile è la capacità di definire regioni specifiche nelle espressioni regolari. Queste regioni speciali possono essere utilizzate come riferimento nelle stringhe sostitutive. Definendo parti specifiche di un'espressione regolare, è quindi possibile fare riferimento a quelle parti con un carattere di riferimento speciale.

Fare back references, devi prima definire una regione e poi fare riferimento a quella regione. Per definire una regione, inseriscibackslashed parenthesesintorno a ciascuna regione di interesse. Viene quindi fatto riferimento alla prima regione circondata da barre rovesciate\1, la seconda regione di \2, e così via.

Supponendo phone.txt ha il seguente testo -

(555)555-1212
(555)555-1213
(555)555-1214
(666)555-1215
(666)555-1216
(777)555-1217

Prova il seguente comando:

$ cat phone.txt | sed 's/\(.*)\)\(.*-\)\(.*$\)/Area \ 
   code: \1 Second: \2 Third: \3/' 
Area code: (555) Second: 555- Third: 1212 
Area code: (555) Second: 555- Third: 1213 
Area code: (555) Second: 555- Third: 1214 
Area code: (666) Second: 555- Third: 1215 
Area code: (666) Second: 555- Third: 1216 
Area code: (777) Second: 555- Third: 1217

Note - Nell'esempio precedente, ogni espressione regolare all'interno delle parentesi sarebbe di nuovo referenziata da \1, \2e così via. Abbiamo usato\per dare un'interruzione di riga qui. Questo dovrebbe essere rimosso prima di eseguire il comando.