Evidentemente, nuestra tarea ha finalizado. Cada tarea parcial ha sido resuelta y podemos construir la orden completa, que sería: [Recuérdese el uso del signo '
\
', explicado el día pasado, para separar líneas de órdenes largas]:dict -d jargon hacker \
| grep -E -o '[{][^[:punct:]]+}' \
| awk 'BEGIN {FS="\n"; print "hacker:"} { print " " $1 }' \
> jargon_ref
Podemos ver el resultado, que se ha guardado en el fichero
jargon_ref
, pidiendo a HAL que nos lo muestre, por ejemplo, con una orden que comentamos en otra sesión:more jargon_ref
Una consideración simple del resultado suscita inmediatamente tres objeciones ---en realidad, cuatro, pero la cuatro la dejamos para más tarde:
- Las referencias están ahí, pero desordenadas. ¿No sería lógico, después de tanto trabajo, obtener, al menos, una lista alfabéticamente ordenada?
- No es aceptable que HAL guarde en un fichero el resultado sin mostrarlo antes. ¿Habrá alguna forma de conseguir que lo muestre y lo guarde a la vez?
- Si volvemos a hacer una consulta al Jargon File sobre un artículo distinto, el fichero
jargon_ref
almacenará las referencias de este último, pero borrará las que ya existían. Debemos modificar la redirección para arreglar este defecto. - ... ??
Todas estas cuestiones no hacen sino refinar, por una parte, el propio planteamiento del problema (cuestiones 1, 2 y 3) y, por otra, poner en evidencia, que en la división de tareas que realizamos no fuimos totalmente fieles a dicho planteamiento (¿cuestión 4?).
Recordemos la forma exacta en que se planteó el problema, expresado entonces bajo el atuendo de un deseo:
Sería magnífico disponer de una lista con las referencias que constan en los artículos que vamos leyendo y guardarla en un fichero.
Refinemos el propio planteamiento para que tenga en cuenta las tres primeras objeciones:
Sería magnífico ver una lista ordenada con las referencias que constan en los artículos que vamos leyendo y a la vez añadirla a un fichero que contendría las referencias cruzadas de todos los artículos que hayamos consultado previamente.
Las nuevas tareas que surgen de esta nueva versión del problema son, expresadas con precisión:
- Ordenar alfabéticamente la lista generada por
grep
antes de queawk
le dé el formato requerido. - Redirigir la salida de
awk
para que se añada al ficherojargon_file
, en lugar de sobreescribirlo. Y, preferentemente, hallar un procedimiento para que, a la vez, nos muestre el resultado actual de su procesamiento.
Ordenar alfabéticamente es muy simple. Podemos pedirle a HAL que "arregle" o "clasifique" (sort en inglés) un fichero alfabéticamente, simplemente diciéndoselo:
sort FICHERO
¡Divino, qué bien sienta el aire puro de las órdenes triviales, sobre todo después de nuestro descenso a los infiernos!
Como muchas otras órdenes de HAL, si no se da un nombre de fichero como argumento, el flujo de texto lo toma del dispositivo de entrada. Por tanto, podemos introducir un simple
sort
en una tubería entre el grep
y el awk
de nuestra orden inicial:dict -d jargon hacker \
| grep -E -o '[{][^[:punct:]]+}' \| sort
\
| awk 'BEGIN {FS="\n"; print "hacker:"} { print " " $1 }' \
> jargon_ref
Conseguir redirigir la salida de una orden a un fichero y a la vez mostrarla en pantalla es igualmente sencillo con la orden
tee
---más aire puro para nuestras neuronas. tee
hace las veces de una 'T' en nuestro arsenal de fontanería ---de ahí su nombre: la pronunciación de la 't' en inglés. Lo que entra en ella sale directamente sin mayor modificación, pero a la vez se redirige al fichero que se le dé como argumento (si el fichero no existe, lo crea por nosotros):
(flujo de entrada) ============= (flujo de salida)
|
|
|
fichero
Por ejemplo, si quiero ver y guardar la lista de mis ficheros en el fichero
mis_ficheros
, le diría a HAL:ls | tee mis_ficheros
Para mayor deleite,
tee
dispone de la opción -a
(de append, que significa "añadir al final"), cuyo propósito es justo lo que ahora nos interesa, a saber, redirigir la entrada al fichero que le demos como argumento, pero sin sobreescribirlo. Y, de modo semejante a como sucedía con el operador de redirección >>
, (el "embudo doble"), tee -a
funciona igual que tee
a secas cuando el fichero dado como argumento no existe.En definitiva, podemos sustituir la ineficaz redirección que formaba parte de nuestra orden primitiva por un
tee -a
empalmado mediante una tubería al resto de la orden y resolver de un plumazo la segunda tarea [llamaré ahora jargon_refs
, en lugar de jargon_ref
al fichero de destino, para verificar desde cero el comportamiento global de nuestra orden modificada]:dict -d jargon hacker \
| grep -E -o '[{][^[:punct:]]+}' \
| sort \
| awk 'BEGIN {FS="\n"; print "hacker:"} { print " " $1 }' \
| tee -a jargon_refs
¿Qué tal, HAL, otra prueba más con esta orden?
dict -d jargon "hacker ethic" \
| grep -E -o '[{][^[:punct:]]+}' \
| sort \
| awk 'BEGIN {FS="\n"; print "hacker ethic:"} { print " " $1 }' \
| tee -a jargon_refs
HAL nos muestra las referencias cruzadas para hacker ethic y guarda la salida en el fichero
jargon_refs
, que ahora presenta el siguiente aspecto, como puede comprobarse si le insistimos a HAL para que nos lo muestre con more jargon_refs
:
hacker:
{bogus}
{cracker}
{geek}
{hacker ethic}
{hack value}
{Internet address}
{the network}
{wannabee}
hacker ethic:
{FidoNet}
{GNU}
{gray hat}
{samurai}
{superuser}
{tiger team}
{Usenet}
Hemos dado fin a nuestra ya bastante larga expedición por los confines de la lengua de HAL. Pero, sin duda, cualquier lector atento que haya llegado hasta aquí se preguntará si no es posible generalizar nuestra solución ya refinada. Tanto esfuerzo como el empleado no merecería menos. ¿No sería posible aliviar definitivamente al humano y construir una instrucción elemental a partir de la que hemos logrado?
Ésta, evidentemente, es la cuarta objeción, por la que antes, y adrede, pasamos de puntillas. El lector está en su pleno derecho de plantearla y de que se le responda. Pero ello nos llevaría a acometer una nueva y muy arriesgada aventura, ya en terrenos en los que sólo los exploradores más incansables osarán aventurarse, territorios donde abandonamos el ámbito del diálogo unívoco con HAL y nos adentramos en el universo de la programación. Que el autor esté dispuesto a emprender esa epopeya, aun en escala mínima, es algo que hasta él mismo ignora. Sea como fuere, aún quedan unos cuantos lugares menos escarpados por explorar.
Resumen
- Un aspecto importante en la resolución de problemas consiste en aceptar la posibilidad de tener que reformular o precisar el propio planteamiento del problema en una fase intermedia del proceso que lleva a su solución.
- La orden
sort
permite ordenar un flujo de texto. - La orden
tee
permite conducir el flujo de entrada hacia la salida y a la vez almacenarla en un fichero. - Generalizar la solución de un problema implica casi siempre utilizar técnicas de programación.
No hay comentarios:
Publicar un comentario