Analiza el archivo desde cierta línea en adelante en bash en Linux

3

Tengo un archivo CSV que contiene los siguientes registros:

Name,Phone,Country
John,N/A,USA
Max,N/A,USA

Name,Color,Size
John,Blue,M
Max,Red,S

¿Cómo puedo leer solo los registros de Nombre, Color, Tamaño y más, usando bash?

Además, ¿cómo puedo limitar la salida hasta que alcance el EOF o una línea en blanco? Así que esto:

Name,Phone,Country
John,N/A,USA
Max,N/A,USA

Name,Color,Size
John,Blue,M
Max,Red,S

Dummy,Dummy,Dummy
Foo,Foo,Bar

No daría salida a esto:

John,Blue,M
Max,Red,S

Dummy,Dummy,Dummy
Foo,Foo,Bar

Pero más bien solo esto:

John,Blue,M
Max,Red,S

Ya probé grep y sed, pero sin suerte, también probé cola pero se desconoce el número de líneas hasta que se lee el archivo.

arielnmz
fuente
Dado que ambos casos pueden parecer similares, el que se propone en la pregunta que hace referencia en realidad incluye el identificador, sin embargo, los datos que se analizan en mi caso solo están separados del resto por el "encabezado" de la tabla, no hay datos después de eso cualquier campo que pueda usarse para recuperarlo, con grep, por ejemplo.
arielnmz

Respuestas:

2

Usando awk

$ awk '/^$/{f=0} f{print} /Name,Color,Size/{f=1}' file
John,Blue,M
Max,Red,S

Cómo funciona

El script awk tiene una variable, fque sirve como indicador para identificar cuándo estamos dentro de un Name,Color,Sizebloque.

  • /^$/{f=0}

    En una línea en blanco, configúrelo f=0para indicar que estamos fuera del Name,Color,Sizebloque.

  • f{print}

    Cuando estemos en el bloque f==1, imprima la línea.

  • /Name,Color,Size/{f=1}

    Cuando lleguemos al Name,Color,Sizeencabezado, configúrelo f=1para indicar que estamos en el bloque.

Usando GNU sed

$ sed -n '/Name,Color,Size/{:a; n; /./{p; ba;}}' file
John,Blue,M
Max,Red,S

Cómo funciona

  • -n

    Indique a sed que no imprima nada a menos que se lo solicitemos explícitamente.

  • /Name,Color,Size/{...}

    Si la línea contiene el Name,Color,Sizeencabezado, ejecute los comandos entre llaves:

    • :a;

      Esto define una etiqueta a.

    • n;

      Esto se lee en la siguiente línea.

    • /./{p; ba;}

      Si la siguiente línea no está en blanco, imprímala ( p) y bifurque ( b) nuevamente en la etiqueta a.

    De esta manera, todas las líneas dentro del bloque se leerán e imprimirán y la impresión se detendrá con la primera línea vacía.

John1024
fuente
1

Puede usar sed para mostrar solo las cosas después de una determinada línea haciendo algo como

sed -e '0,/Name,Color,Size/d' <file>

así que solo verás las líneas que vienen después Name,Color,Size

Eric Renouf
fuente
¡Impresionante, respuesta inmediata! ¿Podría por favor explicar un poco más sobre la sintaxis de ese comando sed? ¿Cuál es el significado de 0,? Además, ¿cómo podría limitar la salida a la primera línea en blanco? En caso de que hubiera otras "tablas" en el mismo archivo?
arielnmz
1
@EricRenouf Después de escribir su respuesta, el OP aclaró sus requisitos: como se muestra en el ejemplo de la pregunta, quiere que la salida se detenga con la primera línea en blanco.
John1024
@arielnmz parece que ya tienes algunas buenas respuestas, pero para responder a tu pregunta sobre lo que está haciendo mi comando sed, aquí va. Por defecto, sed imprimirá cada línea. Lo que hago es eliminar todo, desde la línea 0 ( 0en el comando) hasta la línea que coincide con el patrón que queremos. Por lo tanto, eliminará todas esas líneas de la salida y, de forma predeterminada, imprimirá el resto.
Eric Renouf