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:
-cStampa un contatore delle righe che corrispondono al criterio di ricerca, e non le righe stesse.
-sFunziona in silenzio. Non si produce alcun output ma il codice di ritorno indica se il criterio di ricerca ha trovato almeno una corrispondenza.
-vInverte 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.
-iIgnora maiuscolo/minuscolo sia nel criterio di ricerca che nei dati in input.
-lStampa (elenca) solo i nomi dei file che corrispondono, e non le righe trovate.
-e espressioneUsa 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]