Successivo: Programma id, Precedente: Programma cut, Su: Cloni [Contenuti][Indice]
Il programma di utilità egrep
ricerca occorrenze di espressioni
regolari all’interno di file. Usa
espressioni regolari che sono quasi identiche a quelle disponibili in
awk
(vedi la sezione Espressioni regolari).
Si richiama così:
egrep
[opzioni]'espressione'
file …
espressione è un’espressione regolare. Normalmente, l’espressione
regolare è protetta da apici per impedire alla shell di espandere ogni
carattere speciale come nome-file.
Normalmente, egrep
stampa le righe per cui è stata trovata una
corrispondenza. Se nella riga di comando si richiede di operare su più di un
nome-file, ogni riga in output è preceduta dal nome del file, e dal segno
due punti (:
).
Le opzioni di egrep
sono le seguenti:
-c
Stampa un contatore delle righe che corrispondono al criterio di ricerca, e non le righe stesse.
-s
Funziona in silenzio. Non si produce alcun output ma il codice di ritorno indica se il criterio di ricerca ha trovato almeno una corrispondenza.
-v
Inverte il senso del test. egrep
stampa le righe che
non soddisfano il criterio di ricerca ed esce con successo se il
criterio di ricerca non è soddisfatto.
-i
Ignora maiuscolo/minuscolo sia nel criterio di ricerca che nei dati in input.
-l
Stampa (elenca) solo i nomi dei file che corrispondono, e non le righe trovate.
-e espressione
Usa espressione come regexp da ricercare. Il motivo per cui è prevista l’opzione -e è di permettere dei criteri di ricerca che inizino con un ‘-’.
Questa versione usa la funzione di libreria getopt()
(vedi la sezione Elaborare opzioni specificate sulla riga di comando)
e il programma di libreria che gestisce il passaggio da un file dati
al successivo
(vedi la sezione Trovare i limiti dei file-dati).
Il programma inizia con un commento descrittivo e poi c’è una regola
BEGIN
che elabora gli argomenti della riga di comando usando getopt()
.
L’opzione -i (ignora maiuscolo/minuscolo) è particolarmente facile
da implementare con gawk
; basta usare la variabile predefinita
IGNORECASE
(vedi la sezione Variabili predefinite):
# egrep.awk --- simula egrep in awk # # Opzioni: # -c conta le righe trovate # -s silenziosa: genera solo il codice di ritorno # -v inverte test, successo se regexp non presente # -i ignora maiuscolo/minuscolo # -l stampa solo nomi file # -e espressione da ricercare # # Richiede la funzione getopt() e il programma di libreria # che gestisce il passaggio da un file dati al successivo BEGIN { while ((c = getopt(ARGC, ARGV, "ce:svil")) != -1) { if (c == "c") conta_e_basta++ else if (c == "s") non_stampare++ else if (c == "v") inverti_test++ else if (c == "i") IGNORECASE = 1 else if (c == "l") solo_nomi_file++ else if (c == "e") criterio_di_ricerca = Optarg else sintassi() }
Nel seguito c’è il codice che gestisce il comportamento specifico di
egrep
. Se non è fornito esplicitamente alcun criterio di ricerca
tramite l’opzione -e, si usa il primo argomento sulla riga di
comando che non sia un’opzione.
Gli argomenti della riga di comando di awk
fino ad
ARGV[Optind]
vengono cancellati,
in modo che awk
non tenti di elaborarli come file. Se
non è stato specificato alcun nome di file, si usa lo standard input, e se
è presente più di un nome di file, lo si annota, in modo che i nomi-file
vengano scritti prima di ogni riga di output corrispondente:
if (criterio_di_ricerca == "") criterio_di_ricerca = ARGV[Optind++] for (i = 1; i < Optind; i++) ARGV[i] = "" if (Optind >= ARGC) { ARGV[1] = "-" ARGC = 2 } else if (ARGC - Optind > 1) servono_nomi_file++ # if (IGNORECASE) # criterio_di_ricerca = tolower(criterio_di_ricerca) }
Le ultime due righe sono solo dei commenti, in quanto non necessarie in
gawk
. Per altre versioni di
awk
, potrebbe essere necessario utilizzarle come istruzioni
effettive (togliendo il "#").
Il prossimo insieme di righe dovrebbe essere decommentato
se non si sta usando gawk
.
Questa regola converte in minuscolo tutti i caratteri della riga in input,
se è stata specificata l’opzione -i.80
La regola è
commentata perché non è necessaria se si usa gawk
:
#{ # if (IGNORECASE) # $0 = tolower($0) #}
La funzione a_inizio_file()
è chiamata dalla regola in ftrans.awk
quando ogni nuovo file viene elaborato. In questo caso, non c’è molto da fare;
ci si limita a inizializzare una variabile contatore_file
a zero.
contatore_file
serve a ricordare quante righe nel file corrente
corrispondono al criterio di ricerca.
Scegliere come nome di parametro da_buttare
indica che sappiamo che
a_inizio_file()
è chiamata con un parametro, ma che noi non siamo
interessati al suo valore:
function a_inizio_file(da_buttare) { contatore_file = 0 }
La funzione endfile()
viene chiamata dopo l’elaborazione di ogni file.
Ha influenza sull’output solo quando l’utente desidera un contatore del
numero di righe che sono state individuate. non_stampare
è vero nel
caso si desideri solo il codice di ritorno.
conta_e_basta
è vero se si desiderano solo i contatori
delle righe trovate. egrep
quindi stampa i contatori solo se
sia la stampa che il conteggio delle righe sono stati abilitati.
Il formato di output deve tenere conto del numero di file sui quali si
opera. Per finire, contatore_file
è aggiunto a totale
, in
modo da stabilire qual è il numero totale di righe che ha soddisfatto il
criterio di ricerca:
function endfile(file) { if (! non_stampare && conta_e_basta) { if (servono_nomi_file) print file ":" contatore_file else print contatore_file }
totale += contatore_file }
Si potrebbero usare i criteri di ricerca speciali BEGINFILE
ed
ENDFILE
(vedi la sezione I criteri di ricerca speciali BEGINFILE
ed ENDFILE
),
ma in quel caso il programma funzionerebbe solo usando gawk
.
Inoltre, questo esempio è stato scritto prima che a gawk
venissero
aggiunti i criteri speciali BEGINFILE
ed ENDFILE
.
La regola seguente fa il grosso del lavoro per trovare righe corrispondenti
al criterio di ricerca fornito. La variabile
corrisponde
è vera se la riga è individuata dal criterio di ricerca.
Se l’utente chiede invece le righe che non corrispondono, il senso di
corrisponde
è invertito, usando l’operatore ‘!’.
contatore_file
è incrementato con il valore di
corrisponde
, che vale uno o zero, a seconda che la corrispondenza sia
stata trovata oppure no. Se la riga non corrisponde, l’istruzione
next
passa ad esaminare il record successivo.
Vengono effettuati anche altri controlli, ma soltanto se non
si sceglie di contare le righe. Prima di tutto, se l’utente desidera solo
il codice di ritorno (non_stampare
è vero), è sufficiente sapere
che una riga nel file corrisponde, e si può passare al file successivo
usando nextfile
. Analogamente, se stiamo solo stampando nomi-file,
possiamo stampare il nome-file, e quindi saltare al file successivo con
nextfile
.
Infine, ogni riga viene stampata, preceduta, se necessario, dal nome-file e
dai due punti (:
):
{ corrisponde = ($0 ~ criterio_di_ricerca) if (inverti_test) corrisponde = ! corrisponde contatore_file += corrisponde # 1 o 0 if (! corrisponde) next if (! conta_e_basta) { if (non_stampare) nextfile if (solo_nomi_file) { print nome_file nextfile } if (servono_nomi_file) print nome_file ":" $0 else print } }
La regola END
serve a produrre il codice di ritorno corretto. Se
non ci sono corrispondenze, il codice di ritorno è uno; altrimenti, è zero:
END { exit (totale == 0) }
La funzione sintassi()
stampa un messaggio per l’utente, nel caso
siano state specificate opzioni non valide, e quindi esce:
function sintassi() { print("sintassi: egrep [-csvil] [-e criterio_di_ricerca] [file ...]")\ > "/dev/stderr" print("\n\tegrep [-csvil] criterio_di_ricerca [file ...]") > "/dev/stderr" exit 1 }
Inoltre, qui si introduce un errore subdolo; se una corrispondenza viene trovata, viene inviata in output la riga tradotta, non quella originale.
Successivo: Programma id, Precedente: Programma cut, Su: Cloni [Contenuti][Indice]