Pagina 1 di 1

Grep Multiline matching

Inviato: dom 16 apr 2006, 0:18
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' :'(

Inviato: dom 16 apr 2006, 10:59
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

Inviato: dom 16 apr 2006, 14:24
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"

Inviato: dom 16 apr 2006, 20:37
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

Inviato: dom 16 apr 2006, 21:09
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...!

Inviato: lun 17 apr 2006, 2:41
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 :)