22 agosto, 2009

Manejo avanzado de ficheros en BASH

Cualquier script, en cuanto llega a ser un poco complejo o necesita manejar grandes cantidades de datos hace uso de los ficheros.

El uso intensivo de ficheros no tiene porqué suponer una pérdida de eficiencia muy grande en el script, ya que si un fichero se crea y se destruye en menos de N segundos, éste no llega a ser escrito en disco y sólo existe en memoria. Esa N en linux suelen ser 30 segundos.

El caso es que cuando uno, o al menos yo hasta ahora, piensa en el tratamiento de ficheros en BASH suele ir a pensar en cut, grep, head, tail, sed y amigos.

Después de 10 años he redescubierto ed. Os cuento la bonita historia.

Andaba yo tranquilamente haciendo un script que hace uso de otros scripts antiguos que hice y que, como es BASH, se pueden usar independientemente por línea de órdenes o en otros scripts. Resumiendo, mi problema era que necesitaba mover una linea de un fichero. Esto se puede hacer con una ristra de heads, tails y greps. El caso es que no se cómo llegué a la página de manual de ed y descubro que para mover una linea de sitio en un fichero con ed sólo hay que hacer:
ed $mifichero << EOF
3m7
wq
EOF
Esto coge la línea 3 y la pone como 7.
Otro clásico es querer obtener la línea N de un fichero. Hasta ahora lo que hacía era algo como head -n $N $mifichero | tail -1, pero se esas dos órdenes se pueden quedar en una haciendo:
ed $mifichero <<< "${N}p"
También muchas veces se necesita insertar una cadena en la linea N de un fichero. Pues bien, con ED es algo tan sencillo como:
ed $mifichero << EOF
${N}i
$LineaQueQuieroAnadir
wq


Podría estar muchas páginas hablando de las cosas que se pueden hacer con ed pero lo mejor es que leáis la página del manual de ed. Que ya he escrito bastante y va siendo hora de hacer la comida.

12 agosto, 2009

Cómo hacer trim en Bash

No sé a vosotros, pero a mí en los scripts que hago siempre suelo necesitar hacer trim de una cadena, esto es, eliminar los espacios al comienzo y al final de una cadena.

Bien pues esto es tan «sencillo» como jugar con las expansiones de BASH (más info en man bash), aquí va un ejemplo:
#!/bin/bash
cadena='     prueba de trim        '
#Los :: son para ver claramente los espacios
echo "+ Cadena original ::${cadena}::"
# quito los espacios del principio
cadena="${cadena#"${cadena%%[![:space:]]*}"}"
# quito los espacios del final
cadena="${cadena%"${cadena##*[![:space:]]}"}"
echo "+ Cadena sin espacios ::${cadena}::" 

La salida de este script será
+ Cadena original ::     prueba de trim        ::
+ Cadena sin espacios ::prueba de trim::

Esto es sólo un ejemplo de cosas que se pueden hacer con BASH y que ha acelerado 10 veces un script (antes había sed y cut por todos lados), os recomiendo leeros detenidamente man bash. Tiene cosas muy divertidas, pero eso lo dejaremos para entradas futuras :-)