Grep a partire da un testo fisso, fino alla prima riga vuota


9

Ho un file prova.txtcome questo:

Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random2
random3
random4

extra1
extra2
bla

Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561

extra2
bla
bla

Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random22131

e devo passare da "Inizia a prendere qui" alla prima riga vuota. L'output dovrebbe essere così:

Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random2
random3
random4

Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561

Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random22131

Come puoi vedere le righe dopo "Inizia a prendere qui" sono casuali, quindi -A -B grep flag non funziona:

cat prova.txt | grep "Start to grab from here" -A 15 | grep -B 15 "^$" > output.txt

Potete aiutarmi a trovare un modo per catturare la prima linea che verrà afferrata (come "Inizia ad afferrare da qui"), fino a quando una linea vuota. Non riesco a prevedere quante linee casuali avrò dopo "Inizia a prendere da qui".

Qualsiasi soluzione compatibile con unix è apprezzata (grep, sed, awk è meglio di perl o simili).

EDITATO: dopo una brillante risposta di @ john1024, vorrei sapere se è possibile:

1 ° ordina il blocco (secondo Inizia a prendere da qui: 1 quindi 1 quindi 2)

2 ° rimuovi 4 righe (in ordine alfabetico) fix1, fix2, fix3, fix4 ma sono sempre 4

3 ° alla fine rimuove i duplicati casuali, come il comando sort -u

L'output finale dovrebbe essere così:

# fix lines removed - match 1 first time
Start to grab from here: 1
random1
random2
random3
random4

#fix lines removed - match 1 second time
Start to grab from here: 1
#random1 removed cause is a dupe
random22131

#fix lines removed - match 2 that comes after 1
Start to grab from here: 2
random1546
random2561

o

# fix lines removed - match 1 first time and the second too
Start to grab from here: 1
random1
random2
random3
random4
#random1 removed cause is a dupe
random22131

#fix lines removed - match 2 that comes after 1
Start to grab from here: 2
random1546
random2561

Il secondo output è migliore del primo. È necessaria qualche altra magia di comando unix.


1
Questo è davvero utile per afferrare la traccia dello stack per un particolare thread dall'output jstack java. Sono contento di aver trovato queste domande e risposte!
BenjaminBallard,

Risposte:


13

Usando awk

Provare:

$ awk '/Start to grab/,/^$/' prova.txt
Start to grab from here: 1
random1
random2
random3
random4

Start to grab from here: 2
random1546
random2561

Start to grab from here: 3
random45
random22131

/Start to grab/,/^$/definisce un intervallo. Inizia con qualsiasi riga corrispondente Start to grabe termina con la prima riga vuota ^$, che segue.

Usando sed

Con una logica molto simile:

$ sed -n '/Start to grab/,/^$/p' prova.txt
Start to grab from here: 1
random1
random2
random3
random4

Start to grab from here: 2
random1546
random2561

Start to grab from here: 3
random45
random22131

-ndice a sed di non stampare nulla a meno che non lo chiediamo esplicitamente a. /Start to grab/,/^$/pgli dice di stampare tutte le linee nell'intervallo definito da /Start to grab/,/^$/.


La tua soluzione è perfetta, ho modificato la mia richiesta di aggiungere qualcosa. Relly ringrazia il tuo aiuto. Grazie
heisen

1

Sto pubblicando una soluzione alternativa in quanto può essere utile per casi d'uso di alcune persone. Questa soluzione non è conforme esattamente ai requisiti indicati, per la soluzione migliore vedere la risposta di @ John1024.

Puoi usare awk con il Separatore record impostato su una stringa vuota, awk li interpreterà come righe vuote:

$ awk '/Start/' RS= prova.txt 
Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random2
random3
random4
Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561
Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random22131

Questa versione non conserva le righe vuote nell'output. Mostrerà anche il contesto prima della partita, se presente. Questo comportamento può essere molto utile quando si esegue il grepping per qualcosa in un file e si desidera vedere il blocco delimitato da newline di cui fa parte, ad esempio:

$ awk '/random1546/' RS= prova.txt 
Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561

Ad esempio, lo trovo utile quando si esegue il grepping per cose nei inifile.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.