viernes, noviembre 30, 2012

Guerra y Paz de Tolstoi

Mi hermana me ha hecho entrega del regalo de cumpleaños, un clásico del siglo XIX. La edición es la de Mondadori de tapa dura, traducida por Gala Arias. Cuando he mirado por internet he encontrado opiniones divergentes sobre esta edición, unas criticando la calidad de la traducción y otras ensalzando la misma.

Lo que si parece claro, es que las traducciones al español basadas en una traducción al latín del original en ruso (toma que toma!) contenían muchos errores. La traducción de Mondadori parece estar realizada directamente desde el ruso.

Para ampliar detalles pongo una muestra:

Leer esto da una idea de la complejidad del tema.

jueves, noviembre 29, 2012

Juguete recepcionado

Tras una larga espera, cuatro meses, ya tengo en mi poder una Raspberry Pi con su caja. No he tenido tiempo para probarla, pero este fin de semana reservaré un hueco en la agenda para jugar con ella.

miércoles, noviembre 28, 2012

Brain Training acuático

Es innegable que llevar la cuenta de los largos, mas los diferentes ejercicios en cada serie y coordinar la respiración para adecuarse a los mismos, pone en forma la neurona única y tonifica la memoria.

Por otra parte, he repetido distancia (34 largos = 850 metros) y puedo hacer un largo tomando aire tres veces  (cada once brazadas). Ouh yeah!

sábado, noviembre 24, 2012

34 largos

Hoy he recorrido algo más de distancia, 850 metros, mitad crol y mitad espalda. Sólo me han faltado 150 para hacer el kilómetro. Cuando deje de tomarme los descansos en los bordes recorreré una mayor distancia, pero me cuesta mucho resistirme.

martes, noviembre 20, 2012

Memorias del Hielo

El fin de semana pasado comencé con el tercer libro de la serie Malaz, llamado Memorias del Hielo, que ha superado con creces a los dos anteriores. Menos mal, porque el segundo no me convenció mucho.

En esta ocasión la historia avanza con rapidez, además de que no entra en la dinámica de que cuando va a a pasar algo interesante, te lo corten cambiando la narración a otro personaje. O por lo menos no se nota, porque todo lo que sucede te mantiene intrigado.

PD: Voy por el 30%, puesto que con el kindle desaparecieron los números de página (y su referencia ya no tiene tanta importancia).

Breves notas sobre scripts en bash

Obtener directorio donde se encuentra el ejecutable, asi evitamos tener que configurar una variable con el path del ejecutable (sobre todo el aplicaciones de shell que manejan varios ficheros fuente).
PREFIX=$(readlink -f $(dirname $0))
Redirigir salida dentro de script hacia un fichero de log. Con esto conseguimos que no sea necesario ir añadiendo pipes (>) a cada uno de los comandos de nuestro script y que podamos, al finalizar el script, mandar por mail el log de ejecución.
exec 2>&1 >> LOGERRORES
Añadir elementos a un array.
LISTADO=("${LISTADO[@]}" "ITEM");
Pueden parecer nimiedades, pero no quita que sean muy útiles.

PD: Los script incluidos con '.' (o source) deben terminar con return en lugar de exit. El primero devuelve el control al script que lo invoca, el segundo finaliza la ejecución por completo.

miércoles, noviembre 14, 2012

Arreglando un problema con los tags de svn

Esta mañana me dí cuenta que la aplicación de replica automática de configuraciones tenía un problema con el manejo del repositorio y la creación de los tags (las etiquetas se crean cuando hay un cambio en la configuración de algún dispositivo).

Inicialmente, la aplicación hacia un checkout de todo el repositorio (svn checkout http://repositorio/, que incluye trunk/, tags/ y branches/) pero como en subversion etiquetar es hacer una copia de todo el árbol completo de trunk (svn copy trunk/ tags/nueva-etiqueta; svn commit -m "tag nueva-etiqueta") producía el efecto indeseable de que cada checkout posterior fuera más y más grande. En los inicios esto no supone un problema serio, pero cuando hayan pasado 100 días y si el repositorio ocupara 10 MB, el checkout ocuparía 1 GB (se ejecuta una vez al día y siempre en los dispositivos, aparece alguno que se ha cambiado su configuración, aunque sea en uno sólo, teniendo que hacer el tag), la cosa cambia muchísimo.

Así que me puse a arreglar el problema. La solución es traerme sólo trunk/ (svn checkout http://repositorio/trunk/) y el etiquetado lo hago sobre el propio repositorio (y no sobre la copia local como hacia antes) con el comando svn copy http://repositorio/trunk/ http://repositorio/tags/nueva-etiqueta -m "tag nueva-etiqueta". Se parecen, pero no son iguales.

En subversion los tags son perezosos, no consumen espacio en el repositorio, pero cuando se hacen los checkout de un tag, este sí que se despliega. Si haces el checkout de todos los tags, tendrás todos los tags desplegados.

La verdad que es díficil de ver el problema, sólo me dí cuenta cuando empece a ver en los logs que la operación de checkout inicial cada vez tardaba más en hacerse y cuando lance un du sobre la copia de trabajo, quedó claro el problema.
~/automatic_safe_config$ du -h --max-depth=2 -x
10M ./tags/t20111101
10M ./tags/t20111102
10M ./tags/t20111103
10M ./tags/t20111104
10M ./tags/t20111105
10M ./tags/t20111106
10M ./trunk/
1K. ./branches/
70M ./
Es curioso que antes de dar con la solución, maneje la alternativa de quitar los tags o de pasarme a git. La primera no me gustaba, puesto que quería disponer de la posibilidad de echarle un vistazo rápido a los cambios de configuraciones sin tener que tirar un cliente svn, navegando por los etiquetas. La segunda implicaba muchos mas cambios (montar un servidor git y cambiar todos los comandos svn por sus equivalentes git), y no sabía si iba a tener otro tipo de repercusión.

domingo, noviembre 11, 2012

El buscador automatizado de partidas de ajedrez

Llevaba tiempo haciendo pequeñas chapuzas que me permitieran hacer un trabajo de recopilación de partidas de ajedrez de forma automática. La tarea era complicada por varias razones, primero reconocer dentro del contenido de una página web que hay una partida y luego encontrar un sistema que almacene la partida en una base de datos, detectando duplicidades y eliminando partidas de jugadores con ranking bajo.

Gracias a los consejos de un amigo, que conoce algo de trabajos relacionados con el web crawling (sistemas automatizados para extraer información de la web mediante aplicaciones llamadas spiders), me recomendó la utilización de Scrapy, que es un framework diseñado para estas tareas.

Todavía estoy en la fase de lectura del manual, pero por le menos ya tengo claro que una de las primeras cosas será utilizar Xpath para reconocer las partidas, que están escritas en formato pgn. Esto añade una dificultad, ya que el formato pgn no utiliza etiquetas xhtml para describir la partida y Xpath se apoya en la etiquetas xhtml para detectar los items, que luego serán aprovechados por scrapy.

Por otra parte, Scrapy esta escrito en Python, un lenguaje con el que ya tuve alguna que otra experiencia (Zope/Plone). Python no entra dentro de mis lenguajes de programación favoritos, pero no es complejo y su notación es clara, así que mi adaptación al mismo esta siendo muy rápida.

sábado, noviembre 10, 2012

Bug 10X

He corregido un error en la expresión regular que realizaba la sustitución de la ip del visitante desconocido. La ER no reconocía los números 10X, así que no hacía la sustitución para la creación de la url de búsqueda en ripe.net, mostrando la ip tal cual era.

Semicontención serial

Ya han emitido la mitad de los capítulos de la última temporada de la serie Fringe. Esta vez no los estoy viendo. Los veré cuando estén todos disponibles. No quiero tener que aguantar la espera entre capítulos ni sufrir los parones. Sin embargo, con la segunda temporada de Homeland no he podido resistirme, caí en la trampa del segundo capítulo (Beirut is back).

Supongo que será por culpa de las espectativas. La T1 de Homeland no me gustó del todo, así que por eso  me puse a ver la T2, pensando en dejar de verla. Me equivocaba, doblemente.

La madre parlanchina

Mother tolking = Modern Talking

miércoles, noviembre 07, 2012

Jugando con getopt y getopts

Cuando me he tenido que enfrentar al problema de controlar el paso parámetros en los scripts, siempre lo he dejado como una tarea de google, es decir, que busco por encima lo que necesito, lo adapto a mis necesidades y luego lo olvido. Para la próxima vez, disponde de esta nota, que pretendía ser breve, pero que al final no lo será tanto.

¿Diferencias entre getopt y getopts?

Getopt, en singular, es un comando que permite tratar los parámetros que llegan, sean cortos (del tipo -a, -b, -l) o largos (--long). El segundo es un comando incluido dentro de la bash que solo nos permite operar con los parámetros cortos.

¿Parámetros cortos y largos, con o sin argumentos?

Tanto los parámetros cortos como los largos, pueden tener argumentos (obligatorios o no). Esto se especificará en la cadena de parámetros que se le pasará a getopt/getopts. Por ejemplo, para indicar que vamos a tener dos parámetros sin argumentos podemos utilizar "ab". Si el parámetro 'a' va a llevar un argumento, pondremos "a:b". Si ambos llevan argumento "a:b:". Por último hay un caso más que podemos necesitar, que el parámetro 'a' pueda llevar un argumento, pero que no sea obligatoria la aparición del argumento, entonces la cadena de tratamiento sería 'a::b".

En el caso de los parámetros largos es algo similar. Tenemos el parámetro '--help' y el parámetro '--output=file' con un argumento. La cadena de tratamiento queda como 'help,output:'. Si queremos que '--help' lleve un argumento extra opcional, entonces tendríamos 'help::,output:'. Observese que en este caso, para separar los parámetros largos se utiliza la coma.

¿Cómo usar getopt?

La utilización de getopt es algo compleja de entender, pero con la siguiente estructura de código tenemos el análisis de todos los parametros que le pueden llegar a nuestros scripts con solo unas pequeñas modificaciones (ver ejemplo un poco más abajo).

La estructura va como sigue. Primero se costruye una cadena que contiene la ejecución del tratamiento de parámetro con getopt, indicando los parámetros cortos (-o) y sus versiones largas (--long). Se le pasa también el nombre del programa (-n), se indica cuando hay que dejar de procesar los parámetros (si se encuentra '--') y por último se le pasa la ristra de parámetros que se han recibido ($@). Si hay algun error en el tratamiento, saldremos.

El siguiente paso es evaluar la cadena, es en este momento donde entra en juego el uso de las comillas invertidas en su definición, utilizando set --, para hacer que los argumentos sean evaluados en función de su posición. Con la operación shift iremos desplazándonos entre los argumentos cuando entremos en el bucle, del que saldremos cuando topemos con el parámetro --, que indica que hemos llegado al final de los argumentos recibidos.

Dentro del bucle, hacemos el tratamiento con los case necesarios para los argumentos y si estamos en un argumento que tiene alguna opción, la recogemos al estar en la variable $2 ($1 es la propia opción). Siempre que tratemos un argumento habra que hacer el desplazamiento con shift (uno o dos veces dependiendo de si tiene opción o no), de lo contrario nos quedaremos en el bucle para siempre...
CADPARAM=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \
     -n '$0' -- "$@"`
if [ $? != 0 ] ; then
      echo "Error en el tratamiento de parametros..." 1>&2 ;
      exit 1 ;
fi
# Se hace la evaluacion de los parametros
eval set -- "$CADPARAM"
while true ; do
        case "$1" in
                -a|--a-long) echo "Opcion a" ; shift ;;
                -b|--b-long) echo "Opcion b, argumento \`$2'" ; shift 2 ;;
                -c|--c-long)
                        # c tiene un argumento opcional.
                        # Sera generado vacio aunque no lo encuentre.
                        case "$2" in
                                "") echo "Opcion c, sin argumento"; shift 2 ;;
                                *)  echo "Opcion c, con argumento \`$2'" ; shift 2 ;;
                        esac ;;
                --) shift ; break ;;
                *) echo "Error de tratamiento de opciones!" ; exit 1 ;;
        esac
done
¿Cómo usar getopts?

Getopts es algo similar, solo que suprime la evaluación y no hay bucle con condición true, la propia condición de while va recorriendo los elementos de la lista de argumentos con getopts. Es una construcción algo más sencilla de entender, aunque tiene menos posibilidades.
while getopts "ab:c::" OPCION
do
case $OPCION in
a)
ARGUMENTO1=true
;;
b)
ARGUMENTO2=true
OPT2=$OPTARG
;;
c)
ARGUMENTO3=true
if [ $OPTARG != "" ]; then
OPT3=$OPTARG
fi
;;
*)
echo "Opcion no reconocida"
exit 1
;;
?)
echo "Uso: ejemplo [-a] [-b opcionb] [-c [opcionc]]"
exit 1
;;
esac
done
¿Y después qué?

Getopt y getopts está implementado en bibliotecas para otros lenguajes de programación como C, PHP, Perl, Java. Lo más complicado será encontrar la forma de invocación y la manera en la que iremos paseándonos por los argumentos. El cómo especificar la cadena de argumentos es similar.

Artículo publicado para nomastec :: Jugando con getopt y getops

viernes, noviembre 02, 2012

El bañador olvidado

Da tela de coraje ir a la piscina cuando está lloviendo un viernes por la noche, para tener que volver porque me deje el bañador en casa. Por lo visto, no he sido el primero y tampoco seré el último al que le pase. De todas formas, gracias a la lluvia, me he mojado :-)