¿Qué queremos decir con esto? La mejor manera de verlo es elaborar un fichero
txt2latex.sed
semejante al txt2html.sed
de entonces. El fichero tendría por lo pronto este aspecto:
# Conversión de caracteres especiales
s/"\([[:alnum:]]\+\)"/<<\1>>/g
s/_/\\_/g
# Conversión de etiquetas
s/INICIO SECCIÓN//g
s/FIN SECCIÓN//g
s/INICIO TÍTULO SECCIÓN/\\section{/g
s/FIN TÍTULO SECCIÓN/}\n/g
s/INICIO PÁRRAFO//g
s/FIN PÁRRAFO/\n\n/g
s/INICIO LISTA NUMERADA/\\begin{enumerate}\n/g
s/FIN LISTA NUMERADA/\\end{enumerate}\n\n/g
s/INICIO ELEMENTO LISTA/\\item /g
s/FIN ELEMENTO LISTA/\n/g
s/INICIO NOMBRE PROGRAMA//g
s/FIN NOMBRE PROGRAMA//g
s/INICIO ORDEN//g
s/FIN ORDEN//g
s/INICIO OPCIÓN//g
s/FIN OPCIÓN//g
Buena parte de este fichero se entiende por sí mismo. Las etiquetas informales que no tienen traducción se sustituyen por nada, es decir, se eliminan. También hemos eliminado provisionalmente las etiquetas para nombre de programa, opción y orden, porque todavía no sabemos sus equivalencias en LaTeX. Allí donde queremos un salto de párrafo sustituimos la marca informal por la marca LaTeX equivalente más dos saltos de línea ---recuérdese que el salto de línea se expresa con '
\n
'. Estos dos saltos crean precisamente una línea en blanco. Nótese, en particular, que el carácter '\
' de LaTeX debe escaparse con otro '\
' (el carácter de escape de sed
, y de casi todo en HAL), puesto que es un carácter especial de sed
, justamente el que sirve para escapar un carácter cualquiera.En cuanto a la primera sección del fichero, la relativa a la conversión de las comillas rectas por comillas angulares y la secuencia de escape para el carácter '
_
' explicada ayer, sólo nos puede extrañar la primera orden:s/"\([[:alnum:]]\+\)"/<<\1>>/g
Entender lo que esta orden de
sed
significa implica conocer una nueva posibilidad de sed
todavía no explicada: las referencias hacia atrás (backreferences). Miremos la expresión minuciosamente, porque casi todo nos debería resultar familiar.s/RE
/remplazo/g
es evidentemente una orden de sustitución de
sed
. Lo sustituido es todo lo que encaja con la expresión regular (RE
) que hay a la izquierda. Analicemos primero esa expresión regular:"\([[:alnum:]]\+\)"
Se trata de un molde para un texto entrecomillado (
"texto"
). Lo entrecomillado es un conjunto de caracteres alfanuméricos [[:alnum:]]
. Este conjunto contiene uno o más miembros (el signo +
), que en sed
, frente a lo que ocurre con expresiones regulares extendidas, tiene que escaparse (\+
). Además, este conjunto aparece agrupado (los paréntesis (...)
, que en sed
deben también escaparse). Por tanto, la expresión regular designa todo fragmento de texto constituido por uno o más de un carácter alfanuméricos que esté entrecomillado por comillas rectas. En definitiva, esta expresión regular no contiene nada que no sepamos ya, salvo la necesidad de escapar algunos de sus caracteres.Lo nuevo está en la expresión que se propone como remplazo:
<<\1>>
Las comillas angulares de inicio y cierre son justamente aquellas por las que queremos sustituir las comillas rectas del texto que encaje con la expresión regular. Lo que aparece entre estas comillas angulares es la enigmática expresión
\1
. Esta expresión simplemente recupera el contenido de lo registrado por sed
cuando descubrió una agrupación en la expresión regular, es decir, todo lo que hay entre los paréntesis. (Como sólo se ha registrado una agrupación, la referencia hacia atrás es \1
; si en la expresión regular apareciese una segunda agrupación, la referencia de esta segunda agrupación sería \2
, etc.). Por tanto, el fragmento de texto constituido por los caracteres alfanuméricos va a aparecer intacto en el remplazo. Esta es la técnica habitual que se utiliza cuando una parte interna del texto que encaja con la expresión (en nuestro caso, lo entrecomillado) se quiere preservar y sólo otra parte (en nuestro caso, las comillas rectas) se quiere modificar.Diseccionado el sentido de nuestro fichero
txt2latex.sed
, podemos utilizarlo para efectuar la sustitución de nuestras marcas informales ---que, recuérdese, aparecen en el fichero texto_etiquetado.txt
--- por las de LaTeX y guardar el resultado en un fichero con la extensión .tex
, que es la forma canónica de identificar ficheros LaTeX:sed -f txt2latex.sed texto_etiquetado.txt >texto_etiquetado.tex
El resultado deja mucho que desear:
\section{
Navegación gráfica
}
Si hubiésemos estado visitando la página con un buen navegador gráfico que disponga de la opción de guardar las páginas web como texto, tendríamos que realizar al menos dos acciones, ambas independientes:
...
Los espacios en blanco están por doquier y se han generado saltos de línea donde no debía haberlos.
La causa del problema está en que sed
, tras realizar cada sustitución, incluye el salto de línea en las líneas modificadas. Este comportamiento es conveniente en la mayoría de los casos ---nadie esperaría que sed
se comiese el salto de línea, cuando de lo que se trata es de cambiar sólo una parte de una línea. Sin embargo, este educada manera de obrar es fatal para el caso que nos ocupa.
Hay varias formas de resolver el problema, que pasan por utilizar otro ayudante que no sea sed
. Pero quizá la más sencilla para nuestro caso particular, y que no nos obliga a renunciar a sed
, sea darle como entrada el mismo fichero pero transformado previamente en una única línea. Las marcas seguirán allí intactas y nada provocará saltos de línea innecesarios, más allá de los que nosotros hemos decidido producir en nuestras sustituciones, puesto que sed
trabajará sobre una línea única.
Hacer que las múltiples líneas de un fichero se unan y constituyan una única línea se puede conseguir con distintas órdenes de HAL. Una de las más simples es la orden tr
(de translate). Esta orden dispone de una opción adecuada a nuestros fines, la opción -d
, que elimina (delete) de la entrada el carácter que demos como argumento a esa opción. Por ejemplo:
tr -d 'a'
eliminaría todas las aes de nuestra entrada.
Para convertir múltiples líneas en una única línea, el carácter que deberemos eliminar es justamente el salto de línea. Por tanto:
tr -d '\n'
es la orden apropiada para lograr nuestro propósito.
Hemos dicho que tr
afecta a la "entrada" y no simplemente al "fichero" dado como argumento. ¿Por qué? La razón es que tr
es una de esas pocas órdenes que no permite ficheros como argumentos. Dicho de otra forma, tr
actúa sólo y directamente sobre el flujo de entrada del que se nutre. Esta característica la hace especialmente apta para integrarse en tuberías. Pero en nuestro caso, sigue siendo un fichero el que queremos darle como alimento.
Existe una forma de dar un fichero de alimento a una orden que trabaja únicamente sobre el flujo de entrada. Es una herramienta más de fontanería, el reverso del famoso embudo (>
) que aplicamos para redirigir la salida de una orden a un fichero. Existe otro embudo, <
, que realiza la función contraria: redirige un fichero hacia la entrada estándar. Si en el otro lado (el izquierdo) hay una orden que puede alimentarse directamente desde la entrada estándar (cualquiera de los filtros que hemos visto en anteriores artículos: sed
, grep
, etc.) o que sólo se alimenta de ella, como tr
, el fichero redirigido se convertirá en la entrada de la orden.
En consecuencia, para que nuestra anterior orden de supresión de saltos de línea haga su efecto sobre el fichero texto_etiquetado.txt
, deberíamos decirle a HAL lo siguiente:
tr -d '\n'< texto_etiquetado.txt
Con este paso previo se puede ya construir la orden completa, puesto que el resultado de la acción de tr
se puede enviar sin problemas a sed
mediante una tubería y redirigir lo que produce sed
al fichero texto_etiquetado.tex
:
tr -d '\n'< texto_etiquetado.txt | sed -f txt2latex.sed >texto_etiquetado.tex
Lo cual produce el documento con todas las transformaciones propias de LaTeX que hemos solicitado:
\section{Navegación gráfica}
Si hubiésemos estado visitando la página con un buen navegador gráfico que disponga de la opción de guardar las páginas web como texto, tendríamos que realizar al menos dos acciones, ambas independientes:
\begin{enumerate}
\item Ir al menú <<Archivo>> del navegador y guardar como texto la página web. (Lo que además implica seleccionar un nombre de fichero y un directorio).
\item Crear en Vim una nueva ventana para editar en ella el documento que acabamos de guardar, mediante la orden :new ruta\_fichero.
\end{enumerate}
\section{Navegación desde consola}
Si navegamos con w3m, y gracias a la interacción entre las aplicaciones de consola, bastaría ejecutar una única acción desde el propio Vim, que, además, podríamos abreviar para reproducirla en situaciones semejantes. Veamos cómo.
Con w3m el proceso de convertir una página web en texto es absolutamente elemental: añadir la opción -dump. Por ejemplo:
w3m -dump http://www.w3.org/TR/html401/struct/lists.html
nos devuelve la página dada como argumento, tal cual se presenta en el navegador, pero como puro texto.
Resumen:
- Las expresiones regulares para
sed
no son idénticas a las expresiones regulares extendidas. Ello implica que muchos caracteres típicos de las EREs tengan que escaparse en sed
.
sed
registra las agrupaciones que en los patrones de expresiones regulares aparecen entre paréntesis \(...\)
y los guarda para su uso posterior. Para recuperar lo contenido en esos registros se utilizan los signos de referencias hacia atrás (\1
, \2
, ..., \9
), cada uno de los cuales remite a la primera, segunda, ..., novena agrupación de la expresión regular del caso.
- La orden
tr
traduce o elimina (con la opción -d
) caracteres de la entrada estándar. Por ejemplo tr -d '\n'
elimina los saltos de línea del flujo de entrada.
- Existen órdenes de HAL que se nutren únicamente de la entrada estándar, como
tr
y no pueden recibir un fichero como argumento.
- El embudo
<
permite redirigir un fichero a la entrada estándar y, por extensión, a una orden que se alimente de la entrada estándar. Por ejemplo, tr -d '\n'< mi_fichero
, hace que el fichero mi_fichero
sea la entrada de la orden tr
.
No hay comentarios:
Publicar un comentario