'Heredoc' y la sustitución de variables en BASH
A principios de esta semana estaba copiando del clipboard a vim
, sobre una sesión remota de SSH
, un trozo de código copiado de una web, y el editor insistía en aplicarme un sangrado absurdo que lo descomponía todo, así que en lugar de pelearme con la configuración (no acertaba con el set o unset adecuado, y no sé porqué la ayuda de vim
no estaba instalada), se me ocurrió usar un here document para salir del paso (algo así como documentos empotrados; no me gusta la traducción literal de la Wikipedia
).
Lo fácil que hubiera sido copiar el fichero a disco localmente y usar scp(1)
, ¿verdad? Pero gracias a esa forma, un tanto rara a veces, en la que funciona nuestro cerebro, aprendí una cosa nueva :).
Básicamente los here document (o heredoc), son una funcionalidad que da el shell (y que han heredado algunos lenguajes de programación de alto nivel) que nos permite incluir un documento dentro del propio programa. El operador del shell es <<tag:
#!/bin/sh cat <<FINDOC Esto es un heredoc (o documento empotrado) que hemos incluido en este script. FINDOC
En ese ejemplo cat(1)
mostrará por pantalla todo lo que encuentre hasta llegar a la marca FINDOC
.
Esto es muy útil cuando queremos generar contenido y resulta incómodo poner múltiples lineas con echo(1)
o recurrir a un fichero externo.
En mi caso usé el própio intérprete interactivo para pegar el código, que era un script en shell
precisamente. Usé algo así como:
$ cat >script.sh <<FIN #!/bin/sh ejemplo="hola mundo" echo mensaje $ejemplo FIN
¡Bien! Asunto resuelto y a otra cosa; salvo por el detalle de que el shell interpreta las variables, con lo que el fichero resultante no era el esperado :S.
Entonces el problema pasó a ser el propio heredoc (aquello de que si decides usar X para resolver un problema, tienes dos problemas :D). De hecho es curioso como te olvidas incluso que tu objetivo era realmente copiar un fichero de un sitio a otro ;).
Investigando un poco aprendí algo que no sabía: si ponemos el delimitador entre comillas, ¡no se interpretan las variables!
$ cat >script-2.sh <<"FIN" #!/bin/sh ejemplo="hola mundo" echo mensaje $ejemplo FIN
Podemos comprobarlo con nuestro ejemplo:
$ diff -u script.sh script-2.sh --- script.sh 2010-02-28 19:20:07.755883961 +0000 +++ script-2.sh 2010-02-28 19:20:13.824883877 +0000 @@ -1,5 +1,5 @@ #!/bin/sh ejemplo="hola mundo" -echo mensaje +echo mensaje $ejemplo
La otra opción, que sí conocía, era la de escapar todas las variables y posibles patrones de sustitución ($ejemplo
pasa a ser \$ejemplo
), pero era poco práctico porque el script era bastante largo.
Así que nunca es tarde para aprender cosas nuevas, aunque sea debido a que no usamos la herramienta adecuada para resolver el problema ;).
Actualización: como bonus, the geek joke of the week (my cat is escaped :'D).
Hay 3 comentarios
yo el problema de vi, que no ocurría con gvim lo solucione como indica funky y lo averigüé en :
http://sherekan.com.ar/2009/10/15/vim-en-tu-firefox-con-vimperator/
por nell, en 2010-03-03 17:53:48 ∞
Los comentarios están cerrados: los comentarios se cierran automáticamente una vez pasados 30 días. Si quieres comentar algo acerca de la anotación, puedes hacerlo por e-mail.
por funky, en 2010-03-01 07:52:33 ∞