Grep a partir de un texto fijo, hasta la primera línea en blanco

9

Tengo un archivo prova.txtcomo este:

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

y necesito pasar de "Comenzar a agarrar aquí" a la primera línea en blanco. La salida debería ser así:

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

Como puede ver, las líneas después de "Comenzar a agarrar aquí" son aleatorias, por lo que el indicador grep -A -B no funciona:

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

¿Me pueden ayudar a encontrar una manera de atrapar la primera línea que se tomará (como "Comenzar a tomar desde aquí"), hasta una línea en blanco. No puedo predecir cuántas líneas aleatorias tendré después de "Comenzar a tomar desde aquí".

Cualquier solución compatible con Unix es apreciada (grep, sed, awk es mejor que perl o similar).

EDITADO: después de una respuesta brillante de @ john1024, me gustaría saber si es posible:

1 ° ordenar el bloque (de acuerdo a Comenzar a agarrar desde aquí: 1 luego 1 y luego 2)

2 ° elimina 4 líneas (alfabéticamente aleatorias) fix1, fix2, fix3, fix4 pero siempre son 4

3 ° eventualmente elimina duplicados aleatorios, como el comando sort -u

La salida final debería ser así:

# 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

La segunda salida es mejor que la primera. Se necesita algún otro comando mágico de Unix.

heisen
fuente
1
Esto es realmente útil para obtener el seguimiento de la pila para un subproceso particular de la salida java jstack. Me alegro de haber encontrado estas preguntas y respuestas.
BenjaminBallard

Respuestas:

13

Usando awk

Tratar:

$ 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/,/^$/define un rango Comienza con cualquier línea que coincida Start to graby termina con la primera línea vacía ^$, que sigue.

Usando sed

Con una lógica muy similar:

$ 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

-nle dice a sed que no imprima nada a menos que se lo solicitemos explícitamente. /Start to grab/,/^$/ple dice que imprima cualquier línea en el rango definido por /Start to grab/,/^$/.

John1024
fuente
Su solución es perfecta, he editado mi solicitud para agregar algo. Realmente apreciamos su ayuda. Gracias
heisen
1

Estoy publicando una solución alternativa, ya que puede ser útil para los casos de uso de algunas personas. Esta solución no cumple exactamente con los requisitos establecidos, para la mejor solución vea la respuesta de @ John1024.

Puede usar awk con el Separador de registros establecido en una cadena vacía, awk los interpretará como líneas nuevas en blanco:

$ 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

Esta versión no conserva las nuevas líneas en blanco en la salida. También mostrará contexto antes del partido si está presente. Este comportamiento puede ser muy útil al buscar algo en un archivo y desea ver el bloque delimitado de nueva línea del que forma parte, por ejemplo:

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

Por ejemplo, esto me resulta útil al buscar cosas en los iniarchivos.

htaccess
fuente