Parsear ficheros en Bash

Estos días me veo obligado a estar viviendo en la terminal entre ficheros de log con objeto de detectar fallos y posibles mejoras de un importante procedimiento administrativo en el que andamos inmersos.

Entre las distintas operaciones que realizo sobre los ficheros se encuentra la necesidad de extraer cierta información de los logs para poder compararla con datos de otros ficheros o incluso de las bases de datos.

Considerando que podría ser de interés para algunos de vosotros he optado por compartir algunas formas de extraer información de un fichero de texto.

Datos de ejemplo

Supongamos que tenemos un fichero CSV con un contenido como el siguiente

null

que ha sido obtenido lanzando el siguiente comando en la terminal

for i in {1..15}; do  echo $i";Alumno $i;"$[ ( $RANDOM % 20 )  + 1 ] >> /tmp/lista.lst; done

nuestro objetivo será sacar el contenido de la primera columna que contiene una serie de números que sirven de identificador único de las distintas entradas.

El comando cut

Quizás sea el más sencillo de los dos métodos que vamos a ver.

cat /tmp/lista.lst | cut -d\; -f1

donde:

  1. -d permite indicar el Delimitador o carácter que separa los distintos valores que aparecen en cada fila. Como los datos son un fichero CSV separados por ; y éste tiene sentido en las líneas de comandos Bash (es el separador de diferentes comandos en una pipe) le ponemos por delante la barra invertida (\) para que no lo interprete. Si el separador fuese : bastaría con utilizar en el comando cut un -d:.
  2. -f1 indica la posición de la columna que nos interesa (es 1-index por lo que le estamos pidiendo el primer valor que es el que corresponde con el ID que queremos recuperar)

El comando awk

Aunque pueda resultar algo más engorroso extraer información con awk, presenta como principal ventaja el poder generar resultados más elaborados una vez que le pillas el truco a su sintaxis.

Limitándonos al ejemplo propuesto (obtener los valores de la columna de identificadores) deberíamos lanzar un

cat /tmp/lista.lst | awk -F\; '{ print $1 }'

donde

  1. -F tiene la misma finalidad que el -d del comando cut (la barra invertida es por el mismo motivo)
  2. $1 es equivalente al -f1 de cut.

Conclusión

Dos formas distintas de obtener el mismo resultado (extraer información de un fichero de texto en el que los datos están separador por determinado carácter).

El comando awk, aunque algo más engorroso de escribir nos permite resultados más complejos; sirva como pequeño ejemplo para despertar vuestro interés el siguiente fragmento de código

cat /tmp/lista.lst | awk -F\; '{ print "El ID es " $1 }'

Aunque existen editores de texto (y complementos de GEdit) que permiten la selección de datos por columnas (¿alguien me recomienda uno realmente bueno?)

  • No siempre los delimitadores coinciden en las mismas posiciones por lo que resulta imposible hacerlo con el editor de textos
  • Hacerlo gráficamente es viable cuando lo vamos a hacer una sola vez… si el proceso tenemos que repetirlo múltiples veces se vuelve una auténtica tortura 😉

Espero que el artículo os sea de utilidad.

11 comentarios en “Parsear ficheros en Bash

  1. Pingback: BlogESfera.com
  2. Julio dijo:

    Quizás lo más interesante es poder empezar con la programación de tareas en bash para luego ir complicando el script para realizar tareas más complejas, por ejemplo integrando con correos electrónicos y con acceso a bases de datos o incluso o con otros programas que estén en otros lenguajes (veáse php u otros).

    Un saludo.

    • ¿Es una petición formal de algunos artículos sobre la programación en Bash?

      Curiosamente no suelen tener demasiada aceptación los artículos que sobre el tema he publicado en el blog pero, si os interesan, no tenéis más que pedirlo en los comentarios.

      Salu2 y gracias por la sugerencia @Julio

      • Julio dijo:

        Se me ocurren muchas ideas para poder tratar información con estas técnicas, que seguro para muchos son demasiado aburridas.

        Un ejemplo sería como “consolidar información” que trabajan los profesores a un “repositorio común”, y como procesar distintas alertas y distribuir dicha información procesada a los interesados.

        Ejemplo, cada profesor trabaja unos aspectos en sus clases y los evalúa.

        Para él debe ser fácil ir anotando esta información.

        Cada profesor debe poder saber de manera sencilla, distintas informaciones que saldrán de tratar estadísticamente estos datos.

        Pero el profesor no está solo, no hay un sólo profesor para el alumno. De hecho cada evaluación debe ser compartida con los demás profesores, pues luego hay que dar los resultados a los alumnos, etc, etc. No me quiero enrollar.

        Aquí ya se ven varios aspectos para poder trabajar y seguro que hay tareas en la que bash y la generación de distintos “scripts” puede hacer más fácil y menos tediosa la labor docente.

        Un saludo.

        • Veo que te ha gustado el tema @Julio (me alegro)

          De todos modos para lo que sugieres me metería mejor en el desarrollo de alguna mini aplicación web (php si no te quieres meter en Java) o bien evaluaría alguna de las aplicaciones opensource que existen para la gestión de alumnos 😉

          Un abrazo Julio y, aunque creas que pueda resultar aburrido, estaría encantado de tratar contigo el tema de la gestión docente

  3. hatteras dijo:

    ¿ De donde te has sacado el verbo “parsear” ?
    Si me pongo en la piel de un usuario de windows o de un recién llegado a linux y veo ese “verbo” me asustaria pensando en lo dificil que debe ser un sistema operativo que usa semejante “palabro”.
    En cambio el tema es interesante.

  4. savarito dijo:

    >> Aunque existen editores de texto (y complementos de GEdit) que permiten la selección de datos por columnas (¿alguien me recomienda uno realmente bueno?)

    Puedes usar VIM que admite expresiones regulares. Por ejemplo, para seleccionar la primera columna:

    :/^.\{-};

    Pero también existen plugins para trabajar con archivos CSV en VIM. Por ejemplo:

    http://vim.wikia.com/wiki/Working_with_CSV_files

    Con esto, puedes navegar por las columnas usando HJKL, buscar y sustituir en una columna, borrar columnas e incluso ordenar el texto por columnas.

    A todo esto, ¿no crees que es mejor usar Excel o cualquier hoja de cálculo que permita trabajar con archivos CSV?

    • Sólo soy un iniciado en Vi/Vim por lo que no suelo usarlo como editor por defecto (no me siento lo suficientemente “hombre” para hacerlo ;))

      Respecto a Excel (en su defecto OpenOffice Calc) estaríamos en el mismo problema: tener que hacerlo manualmente con la interacción del usuario lo cual quiero evitar pues lo que busco es poder automatizar el proceso mediante algún script 😉

      Gracias @Savarito por tu participación y sugerencia (echaba de menos que alguien recogiese el pañuelo “lanzado” en el artículo)

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s