domingo, 31 de mayo de 2009

HAL y la burocracia (IV)

Nuestro siguiente paso es imaginar un proceso que, indefectiblemente, nos lleve desde los ficheros de entrada descritos ayer a los informes en pdf requeridos. No es nada de orden diferente a lo que hemos venido haciendo desde el principio de estas conversaciones. En realidad, se trata siempre de lo mismo: pensar en las transformaciones que deben sufrir ciertos datos de entrada para que de ello surja una determinada salida y aplicar las herramientas que HAL pone a nuestra disposición para efectuar dichas transformaciones.

Podemos, pues, como primer acercamiento, aplicar sin miedo el principio explicado hace tiempo: reducir el problema a un caso muy simple y crear un modelo de solución para ese caso.

Asumamos que, en lugar de diferentes informes para múltiples alumnos, queremos generar un único informe para un único alumno ---que sabemos suspenso de antemano. Dicho de otra forma, supongamos que nuestro fichero notas contiene esta única entrada:

Sancho-Panza:1-ge:3

Supongamos, además, que los únicos ficheros de objetivos y contenidos mínimos con los que contamos son ---¡bendita la suerte!--- los de 1-ge, es decir:

1-ge-objetivos.tex
1-ge-contenidos.tex

Supongamos, finalmente ---y para hacer más divertido el ejemplo--- que el contenido de tales ficheros es el siguiente:

  • Contenido de 1-ge-objetivos.tex

    \item Reconocer la diferencia entre los refranes y el buen decir.
    \item Adquirir el hábito del buen decir.
    \item Refrenar el hábito malsano del refraneo sin ton ni son.

  • Contenido de 1-ge-minimos.tex

    \item El refrán y sus muchos peligros.
    \item El decir del caballero versus el decir del bufón.
    \item Síntomas alarmantes de la verborrea refranil.

Para generar con pdflatex un pdf como el que se muestra en la imagen propuesta en el primer artículo de esta serie ---actualizado con los objetivos y contenidos que acabamos de presentar---, deberíamos disponer de un fichero .tex, con un aspecto semejante al siguiente [El preámbulo se omite, y se presupone, sin mayor explicación, que los entornos Objetivos, Contenidos y Propuestas han sido definidos en dicho preámbulo como tipos especiales de listas. (Ver este artículo para refrescar la memoria sobre los entornos y listas en LaTeX)]:

\begin{document}
\begin{datosAlumno}
Alumno: Sancho Panza
Curso: 1.º EE
\end{datosAlumno}

\begin{Objetivos}
\input{1-ge-objetivos}
\end{Objetivos}

\begin{Contenidos}
\input{1-ge-minimos}
\end{Contenidos}

\begin{Propuestas}
???
\end{Propuestas}
\end{document}

Compárese con la plantilla redactada el día pasado:

\begin{document}
\begin{datosAlumno}
Alumno: ALUMNO
Curso: CURSO
\end{datosAlumno}

\begin{Objetivos}
OBJETIVOS
\end{Objetivos}

\begin{Contenidos}
CONTENIDOS
\end{Contenidos}

\begin{Propuestas}
RECUPERACIÓN
\end{Propuestas}
\end{document}

Resulta evidente, que salvo para el caso de las propuestas de recuperación [en púrpura], que discutiremos más adelante, nuestro trabajo, esto es, el trabajo que HAL debería realizar para obtener el fichero .tex del informe de Sancho Panza, digamos, Sancho-Panza.tex, es simplemente sustituir lo que en la plantilla aparece en rojo por lo que, en el mismo color, debe aparecer en el citado informe.

Representemos en lengua de HAL las sustituciones deseadas:

sed 's/ALUMNO/Sancho Panza/' informe_plantilla.tex > Sancho-Panza.tex
sed 's/CURSO/1.º EE/' informe_plantilla.tex > Sancho-Panza.tex
sed 's/OBJETIVOS/\\input{1-ge-objetivos}/' informe_plantilla.tex > Sancho-Panza.tex
sed 's/CONTENIDOS/\\input{1-ge-minimos}/' informe_plantilla.tex > Sancho-Panza.tex

Si utilizamos la opción -e de sed podemos enviar varias órdenes, una tras otra, a sed y reducir la redundancia en las líneas anteriores. Podemos, además, referirnos al fichero que contiene la plantilla a través de la variable PLANTILLA que con ese propósito creamos el día pasado:

sed -e 's/ALUMNO/Sancho Panza/' \
-e 's/CURSO/1.º EE/' \
-e 's/OBJETIVOS/\\input{1-ge-objetivos}/' \
-e 's/CONTENIDOS/\\input{1-ge-minimos}/' $PLANTILLA > Sancho-Panza.tex

Mientras que las dos últimas ordenes de sustitución de la instrucción anterior son válidas tal cual, las dos primeras exigen un tratamiento especial. Las cadenas de caracteres "Sancho Panza" y "1.º EE" no forman parte de nuestros datos de entrada. Debemos, pues, obtenerlas a partir de ellos mediante alguna clase de manipulación. El nombre y curso del alumno, como ya hemos comentado, forman parte del contenido del fichero notas, concretamente, son su primer y segundo campo, respectivamente, donde cada campo está separado por el carácter ':'. Para una operación de extracción de este tipo podemos utilizar, como sabemos, una orden como cut. Así, el campo del nombre se obtendría mediante la orden:

cut -d':' -f1 notas

O, aplicando la variable NOTAS, tal como hemos hecho con la variable PLANTILLA en la instrucción sed anterior:

cut -d':' -f1 $NOTAS

Mutatis mutandis, la siguiente orden extrae del fichero notas el campo relativo al curso:

cut -d':' -f2 $NOTAS

Ahora bien, el contenido de estos campos no es exactamente el que buscamos. El contenido es, respectivamente, Sancho-Panza y 1-ge, pero en el informe deseamos que, en lugar del guión, sea un espacio el que separe nombre y apellido del alumno y que, en lugar de 1-ge aparezca la expresión 1º. EE como identificador del curso ('EE' y 'EP' están por enseñanzas elementales y profesionales, nueva denominación oficial de lo que hace pocos años se denominaban grado elemental y medio, para inri del hacedor de guiones).

sed puede ayudarnos de nuevo a la hora de efectuar las conversiones aludidas.

's/-/ /g'

sustituiría los guiones por espacios en la línea de entrada.

Por su parte la más compleja serie de órdenes

's/\([[:digit:]]*\)-\(.*\)/\1\.º \2/'
's/ge/EE/'
's/gm/EP/'

convertiría 1-ge en 1.º EE [La tercera sustitución, que convierte gm en EP no es necesaria en el caso simple actual, pero la incluimos ya desde ahora mismo con el fin de evitar referirnos a un proceso tan elemental de sustitución en explicaciones posteriores].

Las dos últimas órdenes de esta operación de conversión son obvias, pero la primera puede resultar algo difícil de entender a simple vista. Valga su explicación de repaso de algunas minucias de sed.

Cualquier serie de números que aparezca en la línea de entrada encajará con la expresión '[[:digit:]]*' y cualquier serie de caracteres con la expresión '.*'. Por tanto, el molde '[[:digit:]]*-.*' nos permitirá "cazar" cualquier serie de caracteres constituida por cualquier sucesión de números, seguida de guión y seguido éste último por cualesquiera otros caracteres. En consecuencia, algo como nuestra cadena "1-ge" encajará con ese molde. Puesto que, en la sustitución, queremos reutilizar, por un lado, el número inicial y, por otro, lo que sigue al guión para su posterior conversión mediante las órdenes de sed subsiguientes, guardamos lo que encaje con ambas expresiones en registros temporales, esto es, encerramos entre paréntesis convenientemente escapados los correspondientes moldes, y aplicamos, luego, en el patrón de sustitución, las construcciones especiales \1 y \2 para recuperar lo guardado en dichos registros. El resto es también trivial, el guión acaba sustituido por ".º ", donde el punto debe escaparse, al tratarse de una carácter especial de sed.

Si reunimos todas las piezas, los cut que extraen el nombre y curso del alumno, tal como aparecen en el fichero notas, y los sed que convertirían tales datos al formato que tendrán en el fichero Sancho-Panza.tex de salida, obtenemos estas dos órdenes complejas:

cut -d':' -f1 $NOTAS | sed -e 's/-/ /g'

que devolverá:

Sancho Panza

y la más engorrosa:

cut -d':' -f2 $NOTAS | sed -e 's/\([[:digit:]]*\)-\(.*\)/\1\.º \2/' \
-e 's/ge/EE/' \
-e 's/gm/EP/'

que devolverá:

1.º EE

El paso final está a un tiro de piedra. El resultado de estas dos órdenes debe aparecer como segundo miembro en las instrucciones sed de sustitución propuestas al principio. Este resultado se puede obtener mediante el recurso sintáctico de la sustitución de órdenes. O sea, que nuestro esbozo:

sed -e 's/ALUMNO/Sancho Panza/' \
-e 's/CURSO/1.º EE/' \
-e 's/OBJETIVOS/\\input{1-ge-objetivos}/' \
-e 's/CONTENIDOS/\\input{1-ge-minimos}/' $PLANTILLA > Sancho-Panza.tex

debe completarse como es debido de la forma siguiente:

sed -e 's/ALUMNO/$(cut -d':' -f1 $NOTAS | sed -e 's/-/ /g')/' \
-e 's/CURSO/$(cut -d':' -f2 $NOTAS | sed -e 's/\([[:digit:]]*\)-\(.*\)/\1\.º \2/' \
-e 's/ge/EE/' \
-e 's/gm/EP/')
/' \
-e 's/OBJETIVOS/\\input{1-ge-objetivos}/' \
-e 's/CURSO/\\input{1-ge-minimos}/' $PLANTILLA > Sancho-Panza.tex

¡Buf! algo difícil de digerir de una tacada. Conviene reducir la complejidad a la vista mediante el uso de variables cuyos valores sean las sustituciones de órdenes que acabamos de encajar con calzador:

ALUMNO_OUTPUT=$(cut -d':' -f1 $NOTAS | sed -e 's/-/ /g')
CURSO_OUTPUT=$(cut -d':' -f2 $NOTAS | sed -e 's/\([[:digit:]]*\)-\(.*\)/\1\.º \2/' \
-e 's/ge/EE/' \
-e 's/gm/EP/')

Lo que permite obtener esta expresión final algo más digerible:

sed -e 's/ALUMNO/$ALUMNO_OUTPUT/' \
-e 's/CURSO/$CURSO_OUTPUT/' \
-e 's/OBJETIVOS/\\input{1-ge-objetivos}/' \
-e 's/CONTENIDOS/\\input{1-ge-minimos}/' $PLANTILLA > Sancho-Panza.tex

No estáría mal para un entremés, Sancho amigo, si no fuera porque contiene un grave error. Y es que no hay que descuidarse de los encantamientos que, agazapados en nuestros más inocuos utensilios de cocina, pueden amargar hasta la olla mejor cocinada.

No hay comentarios:

Publicar un comentario