====== Procesamiento de datos por lote ======
==== Escribiendo Scripts para automatizar todo el proceso ====
Referencias:
* [[http://linux.2038bug.com/rute-home.html|Linux: Rute User's Tutorial]]
* [[http://tldp.org/LDP/abs/html/|Advanced Bash Scripting Guide]]
En los artículos anteriores describimos el uso de varias herramientas, y mostramos paso a paso y con creciente complejidad cómo podemos usar estas herramientas para ir desde los datos crudos a la representación gráfica final.
Estos artículos pueden dar la idea de que procesar datos en **Linux** es largo y tedioso, que hay que escribir mucho en la consola o emulador de terminales y que realmente no vale la pena tomarse tanto trabajo.
En realidad los artículos reflejan el proceso mediante el cual un usuario común puede emplear diversas herramientas separadas para lograr un objetivo. Muestra el **análisis** del proceso. Pero falta la **síntesis**: armar un único programa o script que realice todo el proceso en forma automática de manera de simplificarle la vida al pobre y abnegado usuario.
Eso es lo que pensamos mostrar en este artículo.
Para eso es menester comenzar mencionando que al trabajar en una consola un usuario en realidad está trabajando en un entorno de programación, bajo un intérprete de comandos, que en la jerga de **Unix** se llama **Shell**. Existen infinidad de shells para **Unix** o **Linux**: sh, ksh, csh, zsh, ash, bash, etc. (otra vez, etc. no es un shell!)
Hoy por hoy el shell más empleado bajo **Linux** probablemente es **bash**. Cada vez que abrimos una consola o ventana de emulador de terminal, el programa que nos "atiende" es **bash**
En la siguiente figura hemos hecho una captura de pantalla mostrando una ventana del emulador **Konsole**, corriendo **bash** como shell o intérprete de comandos.
{{ :acemu:tutoriales:dataq_di194rs:bash.jpg?500 |Consola corriendo shell bash}}
Bajo este **shell** es que hicimos todo el procesamiento de datos descrito en los artículos anteriores. El entorno de trabajo es extremadamente sencillo: una simple línea de comandos (**CLI**: **C**ommand **L**ine **I**nterface), donde aparece un **prompt** (ken@ae-35:~$) a la derecha del cual aparece el cursor (bloque blanco) donde el usuario escribe las órdenes o comandos que desea ejecutar.
Pero así como podemos escribir órdenes o comandos y ejecutarlos de manera interactiva, también podemos escribir todas estas órdenes en un archivo, indicarle que lo ejecute o interprete con **bash**, darle permisos de ejecución y correr ese programa pasándole datos a procesar para que haga todo de manera automática.
Vamos a mostrar cómo se hace esto.
Ya vimos en los artículos anteriores todos los comandos que deben ejecutarse para lograr el resultado final. La idea es poner todo eso en un único script
=== En el comienzo fue... SheBang! ===
Los **scripts** no son otra cosa que archivos de texto que deben ser interpretados, pero... ¿por quién?
Esto se resuelve agregando en la primer línea del archivo el famoso **shebang** (también conocido como hashbang, hashpling, pound bang, o crunchbang), que no es más que la secuencia **#!**.
Esta secuencia de dos caracteres, se interpreta por el intérprete de comandos desde el cual se lanza la ejecución del archivo como una directiva que le dice qué programa debe emplear para interpretar el conjunto de comandos que sigue en el archivo.
Así, si uno desea escribir un programa en **bash**, pondría en la primer linea del archivo la siguiente directiva:
#!/bin/bash
''/bin/bash'' es donde se encuentra el intérprete de comandos **Bash** del **Linux**.
Si uno quiere escribir un programa en Perl, pondría:
#!/usr/bin/perl
Un programa escrito en Python, usaría el siguiente **shebang**:
#!/usr/bin/python
¿Se entiende la idea?
Ahora bien, si la mayoría de los comandos que ejecutamos lo hicimos empleando **bash** como intérprete, suena lógico usar ese intérprete para armar un programa que haga todo el procesamiento de un saque.
Eso es lo que adjuntamos en el siguiente bloque de código, que escribiremos empleando algún editor de texto: vi, nano, pico, joe, emacs, etc. (otra vez, etc. no es un editor de texto de Linux! ;-)) y luego salvamos al archivo con el nombre ''**programa.sh**''
''Nota: todo texto que aparece después de un "#" es ignorado por el intérprete (salvo el shebang, of course!). Esa es la manera de incluir comentarios en el script, una forma básica de documentación o guía para el usuario''
#!/bin/bash
# Modo de empleo: ./programa.sh archivo_de_datos.csv
# Se supone que el único argumento de entrada del programa es el archivo de datos
# exportado en formato CSV desde el programa de recolección de datos del DataQ
# Mantendremos intácto el archivo original.
orig=$1
# copiamos los datos para preservar el original
cp $orig $$.csv
# Convertimos los datos a formato Unix
dos2unix $$.csv
# Eliminamos líneas en blanco y formateamos los datos de manera adecuada
# Obsérvese cómo encadenamos la ejecución de grep y awk mediante un pipe "|"
grep -v "^$" $$.csv |awk -F"," '
BEGIN {c=0;getline; getline; getline;}
{c=c+1; printf "%-10f %-10f\n", c/s,$1;}' s=60 >$$.xy
# Ahora corremos el programa pyxplot para generar el gráfico
pyxplot <
''**Nota:** el programa de pyxplot lo hemos incluido en el propio script de bash empleando una característica muy curiosa de bash: Here Document
Es una manera de decirle a pyxplot que el programa que queremos que ejecute se encuentra en el propio cuerpo del script. Para eso se usa como ''**marca**'' el **<
chmod 750 programa.sh
Para usar el programa, por ejemplo sobre el archivo **''toma_de_datos_acemumx001.csv''** ejecutamos la orden:
./programa.sh toma_de_datos_acemumx001.csv
Eso genera como salida el archivo:
{{ :acemu:tutoriales:dataq_di194rs:toma_de_datos_acemumx001.csv.pdf |toma_de_datos_acemumx001.csv.pdf}}
que podemos ver con el programa **kpdf** o cualquier visor PDF que tengamos a mano (¿acroread?).
**OJO:** este script es muy básico, apenas aglomera el conjunto de comandos que ensayamos en los artículos anteriores. Puede mejorarse y **mucho!**, pero eso queda como ejercicio para el inadvertido lector ;-)
[[acemu:proyectos:linux:dataq|Volver al artículo principal]]