miércoles, 21 de enero de 2009

HAL y el sol naciente

¿Está HAL dispuesto ya para hablar siempre en nuestra lengua? Lo hemos configurado para que lo haga así cada vez que iniciemos nuestro emulador de terminal. También comprobamos anteriormente que HAL guarda en sus neuronas mensajes en nuestra lengua; en caso contrario, no hubiesen funcionado aquellas órdenes precedidas por la definición de la variable LC_MESSAGES.

Pero ¿hubiese sido así con cualquier otra lengua? Probablemente no. Por la sencilla razón de que para que HAL pueda hablar en todas las lenguas del planeta debe guardar en sus neuronas las adaptaciones de sus respuestas a todas ellas, lo cual es un desperdicio de recursos. Por eso, es frecuente que los arquitectos de las distribuciones no activen el soporte multilingüe más que parcialmente y dependiendo, casi siempre, de las selecciones que el usuario hizo al comienzo de la instalación.

Imaginemos, sin embargo, que, de buenas a primeras y hasta nuevo aviso, nos apetece hablar con HAL en japonés. HAL no puede estar preparado sin más para tales veleidades. ¿Qué hacer en un caso así?

Lo primero ---lo sabemos por lo que vimos el día pasado--- sería modificar el fichero .bashrc de tal manera que, en lugar de:


LANG=es_ES.UTF-8
LANGUAGE=es_ES.UTF-8
LC_ALL=es_ES.UTF-8


tuviésemos esto:


LANG=ja_JP.UTF-8
LANGUAGE=ja_JP.UTF-8
LC_ALL=ja_JP.UTF-8


donde la expresión ja_JP.UTF-8 es la especificación de la lengua oficial japonesa como valor de esas variables.

¡Esta sí que es buena! Todavía no sabemos usar un editor y ahora resulta que tenemos que modificar un fichero. Sabemos añadirle contenido al final, pero de ahí a cambiar el contenido ya existente, y ¡sin un programa de edición en toda regla! El autor se está propasando claramente en sus atribuciones y en sus malditas exigencias.

¡Eh, sin insultar! Que HAL tiene las herramientas suficientes en su maravillosa caja sin necesidad de recurrir aún a programas externos, ¿o todavía lo dudamos?

La herramienta que necesitamos para modificar líneas en un fichero cualquiera se llama sed, que es una abreviatura, justamente, de stream editor (editor de flujo, o de líneas ---para entendernos). sed es una especie de ayudante especializado de HAL, o sea, un HAL diminuto, que también acepta ordenes.

La sintaxis que sigue sed es la siguiente:

sed OPCIONES ORDEN_SED FICHERO >NUEVO_FICHERO,

donde ORDEN_SED es una orden que entiende sed y que le dice qué modificación queremos realizar, FICHERO el nombre del fichero que vamos a modificar y NUEVO_FICHERO el nombre del fichero con las modificaciones efectuadas.

Adviértase que, si no especificamos >NUEVO_FICHERO, es decir, si no redireccionamos el resultado de la modificación, ésta se nos mostrará en el "fichero" en el se muestran por defecto todas las respuestas de HAL, o sea, como ya sabemos desde el día pasado, en la pantalla del terminal desde la que efectuamos la orden. Este comportamiento es conveniente. Sería poco afortunado que la modificación se produjese directamente sobre el fichero que se quiere modificar, puesto que un error nuestro en la determinación de esa modificación sobreescribiría el fichero original, que acabaría corrompido con datos inadecuados. Por eso es común pedir a HAL que, primero, ejecute sed sin la redirección y, sólo cuando estamos seguros de no cometer errores, que lo vuelva a ejecutar con la redirección incluida. Veremos un ejemplo más adelante que lo aclarará del todo.

La parte enigmática del formato sintáctico antes descrito es la que se refiere al tipo de expresiones u órdenes que entiende sed. Se puede obtener una información completa acudiendo a la página de manual sed(1). Como es bastante larga, me tomo la libertad de ahorrarle el trabajo al lector y sugerirle la que conviene en nuestro caso. Lo que queremos que HAL le pida a sed se puede expresar de este modo:

'Sustituye es_ES por ja_JP'

Que, expresado en la lengua de sed, se dice así [es conveniente acostumbrarse a poner la orden entre comillas]:

's/es_ES/ja_JP/'

donde la s es una abreviatura de substitute (sustituye) y donde el trozo de texto que queremos cambiar y su reemplazo aparecen entre barras en primer y segundo lugar, respectivamente.

Con esta breve digresión sobre sed, tenemos casi todas las piezas para lograr modificar el fichero .bashrc. De hecho, ya podemos ver cómo solicitar tal modificación y cuál sería su resultado. ¿Cómo? Ejecutando la orden sin la redirección final:

HAL, dile a sed que sustituya 'es_ES' por 'ja_JP' todas las veces que aparezca en .bashrc

Que sabemos que se dice así:

sed 's/es_ES/ja_JP/' .bashrc

Y el resultado es el esperado [pongo sólo las tres líneas finales]:


...
LANG=ja_JP.UTF-8
LANGUAGE=ja_JP.UTF-8
LC_ALL=ja_JP.UTF-8


Queda sólo apañárselas para que este resultado acabe siendo nuestro nuevo .bashrc.

Pero, ¡cuidado!, no se nos ocurra pedir algo como esto:


sed 's/es_ES/ja_JP/' .bashrc >.bashrc


porque nos quedaríamos con un .bashrc completamente vacío. La razón de ello no es difícil de entender, pero sí algo larga de explicar. Basta, por lo pronto, con saberlo. sed dispone de una opción para hacer precisamente ese cambio sobre el fichero in situ y sin redirección, pero tampoco la vamos a utilizar aquí. Interesa conocer otro procedimiento que, de paso, nos permitirá aprender alguna otra orden y adquirir una buena costumbre.

La buena costumbre es no modificar ningún fichero de la configuración de HAL sin antes hacer una copia de él, por si las moscas. No vaya a suceder que luego queramos volver a la configuración original y no recordemos cómo hacerlo. Sí, sí, ya sé que el día pasado nos saltamos a la torera este recomendación. Entono el mea culpa y me excuso ante HAL y sus secuaces.

Copiar un fichero no entraña ninguna dificultad. Se trata de una instrucción obvia, la instrucción cp (de copy), que recibe dos argumentos: el primero es el nombre del fichero que se va a copiar y el segundo el nombre de la copia. Por tanto, si queremos crear una copia del fichero .bashrc con el nombre .bashrc_ORIGINAL, le diríamos a HAL lo siguiente:

cp .bashrc .bashrc_ORIGINAL

Con esta última pieza del puzle es muy fácil continuar en donde lo habíamos dejado y redondear la orden que queremos darle a HAL:

HAL, dile a sed que sustituya 'es_ES' por a 'ja_JP' todas las veces que aparezca en .bashrc_ORIGINAL y que guarde los cambios en .bashrc

O, lo que es lo mismo:


sed 's/es_ES/ja_JP/' .bashrc_ORIGINAL >.bashrc


Después de esta orden el fichero .bashrc será el fichero modificado que queríamos.

Para volver a la situación original, bastará con que le pidamos a HAL que cambie el nombre de .bashrc_ORIGINAL a .bashrc:

mv .bashrc_ORIGINAL .bashrc

(Y si se tienen dudas sobre esta orden, también se le puede preguntar a HAL: whatis mv)

Conviene, lector, que lo hagas ahora mismo, si no quieres que la próxima vez que abras un terminal lo hagas en una lengua que no conoces ;-) o, mucho más probablemente, empiecen a despistarte mensajes de error sobre las variables de entorno. El próximo día terminaremos la tarea de hacer que HAL hable en japonés, y puedes volver a reproducir lo dicho hoy, lo cual te servirá además de repaso.

Por fin, el resumen:

  • sed es el ayudante de HAL para la transformación de ficheros de texto.

  • La orden para que sed sustituya texto es s, que aparece en expresiones del tipo s/texto_original/reemplazo/. Otras órdenes de sed tienen una sintaxis semejante.

  • cp es la orden para copiar.

  • mv es la orden para renombrar.

  • whatis proporciona una descripción simple de la orden que se le da como argumento.

2 comentarios:

  1. Algunos comandos de HAL no son tan listos como sed y no tienen una opción para modificar ficheros in situ. Por ejemplo, una orden que ya hemos visto: grep. grep tiene una opción para invertir la búsqueda de una palabra. Si quisiéramos deshacer el cambio que hicimos en el .bashrc en la entrada HAL y mis ficheros, podríamos hacer:

    grep -v es_ES .bashrc

    y HAL nos mostraría todas las líneas del .bashrc en las que no encuentre la cadena "es_ES" (es decir, probablemente nos muestre el fichero .bashrc que teníamos antes de ejecutar lo que se dijo en "HAL y mis ficheros"). Sin embargo, de la misma manera que pasa con sed, no podemos hacer:

    grep -v es_ES .bashrc >.bashrc

    porque borraría todo el contenido del .bashrc. Para esto, HAL tiene una orden específica: sponge (viene con el paquete moreutils, no está instalado por defecto). Usando sponge le decimos a HAL: espera a que haya procesado todo el comando anterior antes de empezar a escribir los resultados. Así podríamos hacer:

    grep -v es_ES .bashrc | sponge .bashrc

    y también el ejemplo de esta entrada:

    sed -e 's/es_ES/ja_JP/' .bashrc | sponge .bashrc

    Lo siento si me he salido mucho de la narración que se está siguiendo, pero me está encantando estas conversaciones con HAL y quería aportar mi granito de arena. Sigue así.

    ResponderEliminar
  2. Estupendo, Vicho. Una información muy útil a la que el lector más adicto deberá regresar cuando encontremos el momento de llamar al fontanero de HAL para que ponga sus tuberías donde debe, aspecto crucial de la lengua de HAL, que habrá que tratar en algún momento cercano.

    Todo comentario sabio, como el tuyo, es más que bien recibido. Agradezco tu esfuerzo de haberte amoldado al tenor de la narración. Cosa nada fácil ---supongo--- para alguien acostumbrado a escribir artículos técnicos como los que pones en Debian Package of the Day y que mantienen vivo un proyecto que sigo con gran interés y del que siempre aprendo cosas nuevas.

    ResponderEliminar