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.

sábado, 30 de mayo de 2009

HAL y la burocracia (III - los datos)

Una de las primerísimas cosas que hacemos cuando escribimos un guión para HAL es el análisis de los datos que queremos procesar y de los datos resultantes. En guiones sumamente simples, como los escritos hasta ahora, este análisis se suele realizar de una manera inconsciente. Cuando el guión es algo menos simple resulta casi siempre necesario y, en general, más que recomendable, plantearse conscientemente con qué clase de cosas nos vamos a ensuciar las manos. En guiones complejos, un análisis precipitado conduce, en el mejor de los casos, a un diseño ineficaz y, en el peor, a un resultado infumable.

El guión que nos ocupa es simple y no hace falta demorarse demasiado en esta fase inicial. Por otra parte, hay que buscar un equilibrio entre lo que deseamos hacer y el tiempo que deseamos dedicar a hacerlo. Para un asunto engorroso e impremeditado, como el que seguramente supondría para cualquiera la escritura del actual guión, puede ser suficiente una solución relativamente rápida y sucia. De hecho, el guión propuesto es realmente rápido y sucio. Se puede (¿se debe?) mejorar en muchos sentidos. Pero el tiempo apremia y las ganas son pocas. No obstante, e incluso desde estas premisas, no conviene infringir de entrada absolutamente todas las normas de buen comportamiento. Al menos, veamos por el rabillo del ojo qué cosas están presentes y cuáles aparecerán en nuestra caótica mesa.

Empecemos por lo que queremos obtener. Se recordará de la anterior entrada que lo que se nos pide es un informe por alumno (por cada alumno suspenso). Un fichero pdf por alumno es lo más aconsejable en este caso para obtener una copia impresa, y si además lo generamos vía pdflatex, mejor que mejor.

¿Con qué contamos para poder generar esta serie de ficheros?

Contamos, naturalmente, con la programación de la asignatura. Por suerte, esta programación ---un escrito tan largo como aburrido, plagado de repeticiones internas---, ha sido preparado con LaTeX y está dividido en ficheros independientes que luego se componen en un fichero único. Esta técnica de escribir documentos largos, que tantos quebraderos de cabeza supone para los usuarios de procesadores de textos, es pan comido en el mundo de TeX con una instrucción LaTeX como \input{fichero} o \include{fichero}, que permite incluir el contenido de un fichero dentro de otro. Por tanto, disponemos, para empezar, de ficheros .tex adecuadamente nombrados. Así, por ejemplo, los ficheros que definen los contenidos mínimos por curso, poseen la denominación genérica: curso-nivel-mínimos.tex, donde curso está por 1, 2, 3, etc, y nivel está por ge o gm, abreviaturas de la denominación oficial, en el momento en que se redactó la programación, del grado o nivel de los cursos correspondientes ("grado elemental" y "grado medio", respectivamente).
La sintaxis interna de cada uno de estos ficheros es la que cabe esperar de un fichero LaTeX para listas, en concreto, un texto etiquetado con las siguientes etiquetas, como mínimo:

\begin{itemize}
\item Texto del primer item
...
\end{itemize}

Lo segundo con lo que contamos es con un fichero de texto plano que contiene las notas de los alumnos, el fichero notas. Dicho fichero está compuesto por líneas, cada de una de las cuales es un registro por alumno de la forma:

alumno:curso:nota

y donde, a su vez, el nombre del alumno, primer campo del fichero, responde a la convención sintáctica

Nombre-Apellido1-Apellido2

En concreto, nuestro fichero notas es el siguiente:

Don-Quijote-de-la-Mancha:6-gm:10
Sancho-Panza:1-ge:3
Sansón-Carrasco:3-gm:4
Dulcinea-del-Toboso:1-gm:5

Casi sobra insistir en la decisiva importancia que tiene seguir convenciones sintácticas uniformes en ficheros de texto procesables por HAL, como el descrito.

¿Son estos ficheros suficientes para producir la deseada salida en pdf? Evidentemente, no. Puesto que necesitamos un fichero distinto para cada alumno, debemos crear una plantilla común para todos ellos que se llene con los datos específicos de cada alumno en particular. Puesto que, además, deseamos recurrir a pdflatex para obtener el pdf de cada alumno, este plantilla tiene que ser, ella misma, un fichero .tex. Podremos, entonces, utilizar la instrucción \input para añadir los ficheros de contenidos u objetivos deseados dentro de esa plantilla y utilizar fragmentos de textos apropiados para designar los campos variables en ella. Una plantilla con estas características, que se amolda al documento de salida requerido tendría la forma siguiente:

\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}

Se habrá observado que hemos omitido, para abreviar, el preámbulo del documento LaTeX, donde, además, se tendrían que incluir las definiciones apropiadas de los entornos datosAlumno, Objetivos, Contenidos y Propuestas, definiciones que se establecen mediante la instrucción \newenvironment, que hace las veces de \newcommand, pero en la definición de entornos personalizados, y que no vamos a comentar ahora por tratarse de cuestiones específicas de LaTeX que nos desviarían de nuestro objetivo actual.

En resumen, los datos de entrada imprescindibles de nuestro guión, lo que HAL utilizará para obtener los pdfs, son los siguientes ficheros:

  • Ficheros .tex de los objetivos y mínimos por cursos, ubicados en el directorio que contiene la programación (/home/luis/conservatorio/programacion-loe):

    1-ge-objetivos.tex
    2-ge-objetivos.tex
    ...
    1-gm-objetivos.tex
    2-gm-objetivos.tex
    ...
    1-ge-minimos.tex
    2-ge-minimos.tex
    ...

  • El fichero informe_plantilla.tex que contiene la plantilla para generar los informes por alumno y que reside en el mismo directorio que contiene el guion.

  • El fichero de texto notas que contiene registros por alumno con el formato alumno:curso:nota, ubicado también en el directorio donde reside el guión.


Tras el análisis de los datos de entrada, podemos proceder a indicárselos a HAL:

# Directorio que contiene la programación del curso
PROGRAMACION=/home/luis/conservatorio/programacion-loe

# Fichero que contiene la plantilla LaTeX del informe
PLANTILLA=informe_plantilla.tex

# Fichero que contiene las notas de los alumnos
NOTAS=notas

# Sufijo de los ficheros de objetivos por cursos
OBJETIVOS=objetivos.tex

# Sufijo de los ficheros de contenidos por cursos
CONTENIDOS=minimos.tex

A éstas variables podemos añadir la que corresponde a la nota mínima que debe obtener el alumno para aprobar el curso, un valor que, sin lugar a dudas, tendremos que utilizar en algún momento:

# La nota mínima para aprobar el curso
NOTA_MINIMA=5

Hemos puesto los cimientos. Se observará que estas líneas reproducen tal cual las líneas iniciales del guión completo presentado el día pasado, con la excepción de la variable NOLATEX, cuyo sentido se explicará a su debido tiempo.

Resumen:

  • El análisis de los datos de entrada de un guión es un requisito previo imprescindible en la elaboración de guiones o programas.

  • Los nombres de ficheros de entrada y de los directorios donde residen son candidatos ideales a aparecer como valores de las variables iniciales de un guión.

HAL y la burocracia (II)

El porqué y el para qué del guión propuesto el día pasado es bien simple. A HAL, por descontado, no le interesa lo más mínimo, porque él opera en un nivel de abstracción de orden radicalmente distinto al nuestro, un nivel en el que es totalmente indiferente el asunto sobre el que va a girar nuestro guión del caso. Pero a nosotros, los que leemos o escribimos el guión, nos resulta indispensable, como a cualquier buen novelista, tener algo más que una noción ligera de la materia sobre la que vamos a tratar. En terminología técnica, el asunto sobre el versa en general un programa ---y un guión es un miniprograma, como ya hemos visto--- se suele denominar su dominio.

El dominio de nuestro guión, como resulta fácil de deducir por el nombre dado a algunas de sus variables, tiene que ver con la enseñanza y, en concreto, con el proceso que los pedagogos llaman evaluación. Hasta ahí todos tenemos idea de qué va: un alumno tiene una nota, resultado de su evaluación. El alumno puede aprobar o suspender. En nuestro país la nota mínima suele ser el 5, aunque sobre eso hay discusiones, a veces enconadas ---particularmente, entre alumnos o padres, de un lado, y profesores, del otro---, en las que no vamos a entrar.

Hasta aquí nada nuevo bajo el cielo, ha sido así toda la vida. Pero lo que quizá algunos lectores no sepan es que, una vez que los psicopedagogos y otros teóricos decidieron tomar cartas en el asunto educativo ---con los resultados que todos conocen y que tampoco vamos a comentar en este momento---, se ha producido una proliferación imparable de tecnicismos y de sus correspondientes encarnaciones escritas, que incluyen toda clase de informes, documentos y estadísticas con nombres de significado difuso o simplemente ininteligible y funciones imposibles de describir por una mente como la del autor. En este abigarrado universo lingüístico-burocrático se desenvuelven cotidianamente una parte de las actividades de la comunidad educativa, y cómo no, el procedimiento de evaluación, o séase, el acto de poner el aprobado o el suspenso al alumno.

Como no merece la pena extenderse en el asunto más de lo debido, basten unas mínimas aclaraciones, las suficientes para poder comprender el dominio de nuestro guión.

Las legislaciones educativas del tiempo presente establecen que el contenido de la enseñanza sea programado ---y que se redacte la correspondiente "programación"--- de acuerdo a unos apartados generales definidos por defecto, entre los cuales se encuentran los "objetivos" y los "contenidos", que vienen a ser algo así como la cuenta al detalle en forma de elementos de una lista, de lo que se va a enseñar ---como si esto fuera posible. Dentro de los contenidos, están los "mínimos", que definen, dicho en castizo, lo que el alumno debe saber si no quiere romperse los codos en verano.

Desentrañar la diferencia existente entre "objetivos" y "contenidos" rebasa la competencia lingüística y probablemente mental de la mayoría, incluido el autor, que da por inútil e improcedente el intento de acometer tal empresa.

Pues bien, resulta que de un tiempo a esta parte, cuando un alumno suspende, el profesor está obligado a confeccionar un informe en el que consten, por este orden:

  1. Los "objetivos" que no ha superado.

  2. Los "contenidos" (mínimos) que tampoco ha superado.

  3. Lo que, en concreto, tiene que hacer para superar o "recuperar" dichos "objetivos"-"contenidos" ---y no cuela lo de "estudia, amigo, más te vale".


Si con este conocimiento del dominio volvemos a mirar el código de nuestro guión, veremos que las variables ya tienen todas un significado claro. Del contenido de esas variables, en otras palabras, de los datos concretos ---el papeleo existente y consiguiente--- que vamos a manejar, trataremos en la próxima conversación. Por cierto, que entre tanta pedagogía de nuevo cuño, HAL ha quedado mudo en ésta :-(

Resumen:

  • El conocimiento del dominio sobre el que versa un programa o un guión es un requisito fundamental, previo a cualquier intento de escritura.

domingo, 24 de mayo de 2009

HAL y la burocracia (I)

Entre los muchos impedimentos que han hecho imposible al autor de estos artículos mantener el frenético ritmo de escritura de meses pasados se cuentan las obligaciones laborales, algunas de las cuales han resultado, sin embargo, menos onerosas gracias a la ayuda impagable del propio HAL.

¿Por qué no regresar, al menos provisionalmente, al recuento de estas amigables conversaciones justo para demostrar la utilidad de HAL en esos menesteres tan potencialmente aburridos como inevitables de las tareas burocráticas, ésas de las que echamos pestes, pero que, sin arreglo posible, consumen nuestro precioso tiempo creativo en lo que parece un irrefrenable y pantagruélico festín del papeleo por todos los ámbitos profesionales?

Sí, abandonamos el terreno de las aplicaciones, lo dejamos pendiente hasta mejor ver, para adentrarnos un poco más en el de la conversación compleja, esto es, la escritura de guiones, cuyo colofón aconteció en esta conversación y en las que la precedieron.

Sin mayor explicación y, sin duda, con brutalidad excesiva, veamos el guión que vamos a obtener a lo largo de los próximos días y su efecto inmediato.

Paciencia. El porqué, el para qué y el cómo se explicarán a su debido tiempo (muy pronto). Pero por un sitio hay que empezar y hacerlo de esta forma tan brusca e inopinada es un manera de comprometer al autor y de evitar que siga enmudecido por tiempo indeterminado.

El guion:

#!/bin/sh

#### Directorios y ficheros
# Directorio que contiene la programación del curso
PROGRAMACION=/home/luis/conservatorio/programacion-loe
# Fichero que contiene la plantilla LaTeX del informe
PLANTILLA=informe_plantilla.tex
# Fichero que contiene las notas de los alumnos
NOTAS=notas
# Fichero sed para limpiar etiquetas LaTeX
NOLATEX=limpiar_tex.sed

#### Datos estáticos (constantes)
# Sufijo de los ficheros de objetivos por cursos
OBJETIVOS=objetivos.tex
# Sufijo de los ficheros de contenidos por cursos
CONTENIDOS=minimos.tex
# La nota mínima para aprobar el curso
NOTA_MINIMA=5

for linea in $(cat $NOTAS)
do
if [ $(echo $linea | cut -d':' -f3) -lt $NOTA_MINIMA ]
then
# Nombre y curso del alumno tal como constan en el fichero $NOTAS
ALUMNO=$(echo $linea | cut -d':' -f1)
CURSO=$(echo $linea | cut -d':' -f2)

# Nombre y curso con el formato que tendrán en la salida impresa
ALUMNO_OUTPUT=$(echo $ALUMNO | sed -e 's/-/ /g')
CURSO_OUTPUT=$(echo $CURSO | sed -e 's/\([[:digit:]]*\)-\(.*\)/\1\.º \2/' \
-e 's/ge/EE/' \
-e 's/gm/EP/')

# Ficheros que contienen los objetivos y contenidos del curso
# en que el alumno está matriculado
F_OBJETIVOS=${PROGRAMACION}/${CURSO}-$OBJETIVOS
F_CONTENIDOS=${PROGRAMACION}/${CURSO}-$CONTENIDOS

# Los objetivos y contenidos en un formato apto para la plantilla
# a partir de la que se genera el informe
sed -f $NOLATEX $F_OBJETIVOS > objetivos_tmp.tex
sed -f $NOLATEX $F_CONTENIDOS > contenidos_tmp.tex

# Las propuestas de trabajo se deben introducir interactivamente
echo "Introduzca propuestas de trabajo para $ALUMNO_OUTPUT [\item ... (^D para salir)]: "
cat > trabajo_tmp.tex

# Construcción del fichero .tex del informe a partir de la plantilla
sed -e "s/ALUMNO/$ALUMNO_OUTPUT/" \
-e "s/CURSO/$CURSO_OUTPUT/" \
-e 's/OBJETIVOS/\\input{objetivos_tmp}/' \
-e 's/CONTENIDOS/\\input{contenidos_tmp}/' \
-e 's/RECUPERACIÓN/\\input{trabajo_tmp}/' $PLANTILLA > ${ALUMNO}.tex

# Generación del pdf del informe e impresión
pdflatex ${ALUMNO}.tex > /dev/null
# okular ${ALUMNO}.pdf 2> /dev/null &
lp ${ALUMNO}.pdf > /dev/null

# Eliminación del los ficheros temporales creados
rm *_tmp.tex
rm $(ls ${ALUMNO}* | grep -v '\.pdf')
fi
done

Un fragmento del resultado: