7.2 Comandi di manipolazione del testo

Tabella 7-1. Comandi di manipolazione del testo

Comando/Sintassi Cosa fa
awk/nawk [opzioni] file esamina gli schemi (pattern) all'interno di un file ed elabora i risultati
grep/egrep/fgrep [opzioni] 'stringa di ricerca' file ricerca nell'argomento (in questo caso probabilmente un file) tutte le occorrenze della stringa di ricerca e le elenca
sed [opzioni] file editor di flusso per manipolare file da uno script o da linea di comando

7.2.1 grep

Questa sezione fornisce un'introduzione all'uso delle espressioni regolari con grep(1).

L'utility grep(1) viene usata per ricercare espressioni regolari comuni che si presentano nei file Unix. Le espressioni regolari, come quelle viste in precedenza, sono meglio specificate all'interno di apostrofi (o caratteri di quoting singoli) quando usate con l'utility grep(1). L'utility egrep(1) fornisce una capacità di ricerca attraverso un set esteso di meta-caratteri. La sintassi dell'utility grep(1), alcune delle possibili opzioni e alcuni semplici esempi sono mostrati di seguito.

Sintassi

grep [opzioni] expreg [file]

Opzioni generali

-i ignora la differenza tra caratteri maiuscoli e minuscoli
-c riporta solamente la somma del numero di linee contenenti le corrispondenze, non le corrispondenze stesse
-v inverte la ricerca, visualizzando solo le linee senza corrispondenza
-n mostra un numero di linea insieme alla linea su cui è stata trovata una corrispondenza
-s lavora in silenzio, riportando solo lo stato finale:
  0, per corrispondenze trovate
  1, per nessuna corrispondenza
  2, per errori
-l elenca i nomi dei file, ma non le linee, nei quali sono state trovate corrispondenze

Esempi:

Si consideri il seguente file:

{Unix prompt 5} cat num.list
 1      15 fifteen
 2      14 fourteen
 3      13 thirteen
 4      12 twelve
 5      11 eleven
 6      10 ten
 7       9 nine
 8       8 eight
 9       7 seven
10       6 six
11       5 five
12       4 four
13       3 three
14       2 two
15       1 one

Ecco alcuni esempi di grep(1) usando tale file. Nel primo si ricerca il numero 15:

{Unix prompt 6} grep '15' num.list
 1      15 fifteen
15       1 one

Ora si usa l'opzione -c per contare il numero di linee che corrispondono al precedente criterio di ricerca:

{Unix prompt 7} grep -c '15' num.list
2

Qui la ricerca è più generale: si selezionano tutte le linee che contengono il carattere 1 seguito da un 1 o un 2 o un 5:

{Unix prompt 8} grep '1[125]' num.list
 1      15 fifteen
 4      12 twelve
 5      11 eleven
11       5 five
12       4 four
15       1 one

Ora si ricercano tutte le linee che iniziano con uno spazio:

{Unix prompt 9} grep '^ ' num.list
 1      15 fifteen
 2      14 fourteen
 3      13 thirteen
 4      12 twelve
 5      11 eleven
 6      10 ten
 7       9 nine
 8       8 eight
 9       7 seven

Ora tutte le linee che non iniziano con uno spazio:

{Unix prompt 10} grep '^[^ ]' num.list
10       6 six
11       5 five
12       4 four
13       3 three
14       2 two
15       1 one

L'ultimo esempio può anche essere realizzato usando l'opzione -v insieme all stringa di ricerca originale, esempio:

{Unix prompt 11} grep -v '^ ' num.list
10       6 six
11       5 five
12       4 four
13       3 three
14       2 two
15       1 one

Ora si ricercano tutte le linee che iniziano con carattere compreso tra 1 e 9:

{Unix prompt 12} grep '^[1-9]' num.list
10       6 six
11       5 five
12       4 four
13       3 three
14       2 two
15       1 one

In questo esempio si ricercano alcune istanze di t seguite da zero o alcune occorrenze di e:

{Unix prompt 13} grep 'te*' num.list
 1      15 fifteen
 2      14 fourteen
 3      13 thirteen
 4      12 twelve
 6      10 ten
 8       8 eight
13       3 three
14       2 two

In questo esempio si ricercano alcune istanze di t seguite da una o alcune occorrenze di e:

{Unix prompt 14} grep 'tee*' num.list
1      15 fifteen
2      14 fourteen
3      13 thirteen
6      10 ten

Si può prendere il proprio input da un programma, anzichè da un file. Qui si riportano alcune linee di output del comando who(1) che iniziano con la lettera l.

{Unix prompt 15} who | grep '^l'
lcondron ttyp0 Dec 1 02:41 (lcondron-pc.acs.)

7.2.2 sed

L'editor di flusso non interattivo sed(1) manipola un flusso di input, linea per linea, creando specifici cambiamenti e mandando il risultato su standard output.

Sintassi

sed [opzioni] comando_di_editing [file]

Il formato per i comandi di editing è:

[indirizzo1[,indirizzo2]] [funzione] [argomenti]

dove gli indirizzi sono facoltativi e possono essere separati dalla funzione tramite spazi o tab. La funzione è obbligatoria. L'argomento può essere facoltativo o obbligatorio a seconda della funzione usata.

Gli indirizzi di linea numerati sono numeri decimali di linea che partono dalla prima linea di input e si incrementano di uno per ogni linea. Se vengono stabiliti più file di input il contatore continua cumulativamente attraverso i file. L'ultima linea di input può essere specificata con il carattere $.

Gli indirizzi di contesto sono schemi di espressioni regolari racchiusi tra caratteri di slashe (/).

I comandi possono avere 0, 1 o 2 indirizzi separati da virgola con i seguenti effetti:

# indirizzi linee considerate
0 tutte le linee di input
1 solamente le linee che corrispondono agli indirizzi specificati
2 dalla prima linea che corrisponde al primo indirizzo fino alla linea che corrisponde al secondo indirizzo, inclusa. Il processo viene ripetuto per le linee interne.

Le funzioni di sostituzione permettono di ricercare contesti e sono specificate nella forma:

s/schema_espressione_regolare/stringa_di_rimpiazzo/flag

e possono essere quotate con caratteri di quoting singoli (') se sono specificate opzioni o funzioni aggiuntive. Questi schemi sono identici agli indirizzi di contesto, eccetto che, mentre questi sono normalmente chiusi tra slashe (/), nelle funzioni sono permessi alcuni normali caratteri per specificare i delimitatori, oltre a newline e spazio. La stringa di rimpiazzo non è uno schema di espressione regolare; qui i caratteri non hanno significati speciali, fatta eccezione di:

& che sostituisce tale simbolo con la stringa schema_espressione_regolare
\n sostituisce tale simbolo con l'n-esima stringa corrispondente a schema_espressione_regolare chiusa tra una coppia di '\(','\)'

Questi caratteri speciali possono essere messi in escape con il carattere backslash (\) per rimuovere il loro significato speciale.

Opzioni generali

-e script script di editing
-n non stampa l'output di default, ma solamente quelle linee specificate dalle funzioni p o s///p
-f script_file prende lo script di editing dal file specificato

Alcune valide flag per le funzioni sostitutive sono:

d cancella lo schema
g sostituzione globale dello schema
p stampa le linee

Esempi:

Questo esempio modifica tutte le accidentali virgole (,) in una virgola seguita da uno spazio (, ) quindi crea l'output:

% cat filey | sed s/,/,\ /g

Il seguente esempio rimuove tutte le accidentali Jr precedute da uno spazio (Jr) all'interno del file filey:

% cat filey | sed s/\ Jr//g

Per realizzare operazioni multiple sull'input, si precede ogni operazione con l'opzione -e (edit) e si quota la stringa. Ad esempio, per filtrare le linee contenenti “Date: ” e “From: ” e rimpiazzarle senza i due punti (:):

% sed -e 's/Date: /Date /' -e 's/From: /From /'

Per visualizzare solamente le linee del file che iniziano con “Date:” e includerne una che inizia con “Name:”:

% sed -n '/^Date:/,/^Name:/p'

Per stampare solamente le prime 10 linee dell'input (un rimpiazzo di head(1)):

% sed -n 1,10p

7.2.3 awk, nawk, gawk

awk(1) è un linguaggio di elaborazione e ricerca di schemi. Il suo nome deriva dalle ultime iniziali dei tre autori: Alfred. V. Aho, Peter. J.Weinberger e Brian. W. Kernighan. nawk è un nuovo awk(1), una nuova versione del programma e gawk(1) è il gnu awk(1), da parte della Free Software Foundation. Ogni versione è leggermente differente. Qui ci si limiterà ad illustrare semplici esempi che potrebbero andar bene per tutte le versioni. In alcuni sistemi operativi awk(1) è in realtà nawk.

awk(1) ricerca schemi nel suo input e realizza le operazioni specificate su ogni linea o sui campi di linea che contengono tali schemi. Le espressioni dello schema di confronto per awk(1) possono essere specificate sia attraverso linea di comando, sia inserendole in un file e usando l'opzione -f file_programma.

Sintassi

awk programma [file]

dove programma è composto da uno o più dei seguenti campi:

schema { azione }

Ogni linea di input viene verificata con lo schema di confronto insieme alla specifica azione che bisogna realizzare per ogni corrispondenza trovata. Questo continua attraverso la completa sequenza di schemi, quindi la prossima linea di input viene verificata.

L'input è diviso tra record e campi. Il separatore di record di default è newline e la variabile NR tiene il conto dei record. Il separatore di campo di default è uno spazio bianco, spazi e tab, e la variabile NF tiene il conto dei campi. I separatori di input del campo, FS e del record, RS, possono essere settati in qualsiasi momento per farli corrispondere a singoli caratteri specifici. I separatori di output del campo, OFS e del record, ORS, possono essere modificati, se si desidera, con singoli caratteri specifici. $n, dove n è un intero, viene usato per rappresentare l'n-esimo campo di un record di input, mentre $0 rappresenta l'intero record di input.

BEGIN e END sono speciali schemi che vengono verificati rispettivamente all'inizio dell'input, prima che il primo campo sia letto e alla fine dell'input, dopo che l'ultimo campo è stato letto.

La stampa è permessa attraverso l'istruzione print e l'istruzione per la stampa formattata printf.

Gli schemi (pattern) possono essere espressioni regolari, espressioni aritmetiche relazionali, espressioni di valutazione di stringhe e combinazioni buleane di alcune di queste. In quest'ultimo caso gli schemi possono essere combinati con i seguenti operatori buleani, usando le parentesi per definire le combinazioni:

|| or
&& and
! not

La separazione di schemi con virgole definisce un range in cui lo schema è applicabile, esempio:

/primo/,/ultimo/

seleziona tutte le linee partendo con quella che contiene primo e continuando inclusivamente fino alla linea che contiene ultimo.

Per selezionare le linee da 15 a 20 si usa il seguente schema:

NR==15 , NR==20

Le espressioni regolari devono essere chiuse tra slashe (/) e i meta-caratteri possono essere messi in escape con il carattere di backslash (\). Le espressioni regolari possono essere raggruppate con gli operatori seguenti:

| per alternative separate
+ una o più
? zero o una

Un confronto di espressione regolare può essere specificato con:

~ contiene l'espressione
!~ non contiene l'espressione

Quindi il programma:

$1 ~ /[Ff]rank/

è vero se il primo campo, $1, contiene "Frank" o "frank" dovunque all'interno del campo. Per confrontare un campo identico a "Frank" o "frank" si usa:

$1 ~ /^[Ff]rank$/

Le espressioni relazionali sono permesse usando i seguenti operatori relazionali:

< minore di
<= minore o uguale a
= = uguale a
>= maggiore o uguale a
!= non uguale a
> maggiore di

Non si può conoscere su due piedi se le variabili sono stringhe o numeri. Se nessun operando è riconosciuto per essere un numero, sono realizzati confronti di stringhe. Altrimenti, viene realizzata una comparazione numerica. In mancanza di informazioni per il contrario, viene realizzata una comparazione di stringa, così questa:

$1 > $2

verrà valutata con valori di tipo stringa. Per assicurarsi una valutazione numerica, costruire qualcosa simile a:

( $1 + 0 ) > $2

Le funzioni matematiche exp, log e sqrt sono di tipo built-in.

Altre funzioni built-in sono:

index(s,t) ritorna la posizione della stringa s dove si presenta il primo t o 0 se non esiste
lenght(s) ritorna la lunghezza della stringa s
substr(s,m,n) ritorna l'n-esimo carattere della sottostringa di s, iniziando dalla posizione m

Gli array sono dichiarati automaticamente quando vengono usati, per esempio:

arr[i]=$1

assegna il primo campo del corrente record di input all'i-esimo elemento dell'array.

Le espressioni di controllo di flusso if-else, while e for sono permesse con la sintassi del C:

for (i=1; i <= NF; i++) {azioni}

while (i<=NF) {azioni}

if (i<NF) {azioni}

Opzioni generali

-f file_programma legge i comandi dal file specificato
-Fc usa il carattere c come il carattere di separatore di campo

Esempi:

% cat filex | tr a-z A-Z | awk -F: '{printf("7R %-6s %-9s %-24s \n",$1,$2,$3)}' > upload.file

effettua cat su filex, che è formattato in questo modo:

nfb791:99999999:smith
7ax791:999999999:jones
8ab792:99999999:chen
8aa791:999999999:mcnulty

cambiando tutti i caratteri minuscoli in caratteri maiuscoli con l'utility tr(1) e formattando il file come mostrato di seguito, il quale viene scritto nel file upload.file

7R NFB791 99999999 SMITH
7R 7AX791 999999999 JONES
7R 8AB792 99999999 CHEN
7R 8AA791 999999999 MCNULTY

Questo, ed altri documenti, possono essere scaricati da ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

Per domande su FreeBSD, leggi la documentazione prima di contattare <[email protected]>.
Per domande su questa documentazione, invia una e-mail a <[email protected]>.