Grep Multiline matching

Postate qui per tutte le discussioni legate a Linux in generale.

Moderatore: Staff

Regole del forum
1) Citare sempre la versione di Slackware usata, la versione del Kernel e magari anche la versione della libreria coinvolta. Questi dati aiutano le persone che possono rispondere.
2) Per evitare confusione prego inserire in questo forum solo topic che riguardano appunto Gnu/Linux in genere, se l'argomento è specifico alla Slackware usate uno dei forum Slackware o Slackware64.
3) Leggere attentamente le risposte ricevute
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
Rispondi
h8er
Linux 1.x
Linux 1.x
Messaggi: 111
Iscritto il: dom 10 ott 2004, 0:00

Grep Multiline matching

Messaggio da h8er »

ciao avrei una domanda da farvi, grep supporta il matching di espressioni regolari su più linee ?? mi spiego, dato un file di testo così fatto

:::nome1
linea\n
linea\n
linea\n

:::nome2
linea\n
linea\n
linea\n

:::nome3
linea\n
linea\n
linea\n

ecc ecc.. ora io vorrei catturare ad esempio tutte le linee da :::nome2 al seguente ::: con powergrep per windows riesco a trovare correttamente le varie linee con un espressione del tipo

Codice: Seleziona tutto

:::.*?nome2(.|\n)*?\n:::
ma in grep gnu non funziona.. sapete aiutarmi ?? non ditemi che non si puo' :'(

Avatar utente
alessiodf
Linux 3.x
Linux 3.x
Messaggi: 823
Iscritto il: ven 14 ott 2005, 21:04
Slackware: current
Kernel: 2.6.26.4
Desktop: Kde 4.1
Località: Roma
Contatta:

Messaggio da alessiodf »

Codice: Seleziona tutto

cat file.txt | awk -v FS="\n" -v RS='' '/:::nome2/{print $0}' 
Dove file.txt è in tuo file... e la parte /:::nome2/ è il record che vuoi ricavare... in questo caso viene:

Codice: Seleziona tutto

alessio@skynet[~]$ cat a.txt | awk -v FS="\n" -v RS='' '/:::nome2/{print $0}'
:::nome2
linea\n
linea\n
linea\n
:wink: Potentissimo AWK! 8)

Volendo puoi addirittufa prendere solamente alcune delle "linea/n".. certo, forse è sprecato usare awk...ma non mi veniva altro in mente! :D

Avatar utente
Paoletta
Staff
Staff
Messaggi: 3975
Iscritto il: lun 25 apr 2005, 0:00
Slackware: 14.2 - 64 bit
Desktop: fluxbox
Località: Varese

Messaggio da Paoletta »

se conosci il numero delle linee che ti interessano puoi sfruttare l'opzione -A

Codice: Seleziona tutto

cat file.txt | grep -A 3 "nome2"

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6643
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Messaggio da targzeta »

alessiodf ha scritto:

Codice: Seleziona tutto

cat file.txt | awk -v FS="\n" -v RS='' '/:::nome2/{print $0}' 
Ci tengo a dire che:
1) Si può eliminare la pipeline in questo modo:

Codice: Seleziona tutto

awk -v FS="\n" -v RS='' '/:::nome2/{print $0}' file.txt
2) Questo comando non fa esattamente quello richiesto perchè in una situazione come questa:

Codice: Seleziona tutto

:::nome2 
linea 
linea 
linea 
:::nome3 
linea 
linea 
linea
non funzionerebbe. Provare per credere!
awk è potente...se lo sai usare :wink: .

In alternativa, visto che neanche io so esattamente se con grep si può fare (prego h8er di farlo sapere se riesce a scoprire come), si può usare questo comando

Codice: Seleziona tutto

sed -n '/:::nome2/{b label;};d;:label /:::.*:::/{x;p;q;};{h;N;b label}' file.txt
per non scomodare awk.

Se vuoi sapere esattamente cosa fa questo script per sed te lo posso spiegare in dettaglio. Non lo faccio ora perchè
verrebbe un post lungo ed ho constatato che i post lunghi molto spesso vengono ignorati (fatica sprecata insomma) :lol: .

Spina

Avatar utente
alessiodf
Linux 3.x
Linux 3.x
Messaggi: 823
Iscritto il: ven 14 ott 2005, 21:04
Slackware: current
Kernel: 2.6.26.4
Desktop: Kde 4.1
Località: Roma
Contatta:

Messaggio da alessiodf »

spina ha scritto: 2) Questo comando non fa esattamente quello richiesto perchè in una situazione come questa:

Codice: Seleziona tutto

:::nome2 
linea 
linea 
linea 
:::nome3 
linea 
linea 
linea
non funzionerebbe. Provare per credere!
awk è potente...se lo sai usare :wink: .
Bhe..certo.. ti assicuro che awk lo so usare bene.. e serve per la scansione e la ricerca nei record... quello che hai scritto tu cos'è??? e' solamente un file di testo, ma quello che ha proposto h8er è un'altra cosa...!

h8er
Linux 1.x
Linux 1.x
Messaggi: 111
Iscritto il: dom 10 ott 2004, 0:00

Messaggio da h8er »

grazie a tutti per avermi risposto in particolare a spina per avermi fatto notare sed con la sua sintassi, in realtà l'esempio era semplificato poichè in realtà devo trovare nello stesso file più linee tra i tag ::: ::: e sopratutto il "nome2" non è unico ma me lo posso ritrovare in stringhe più complicate comunque ho risolto così (non è finissima la cosa ed è ampiamente ottimizzabile ma fa il suo sporco lavoro, assembly rulez :twisted: )

Codice: Seleziona tutto

sed -n ':label1 /:::.*nome2.*/{p;:label2 n; /:::/ !{p;b label2;};b label1;};n; b label1;' file
PS: per grep mi sa proprio che non supporta il matching multilinea ma lo fa alla grande sed quindi direi che non c'è problema :)

Rispondi