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.