Cosas que se aprenden: Cat y grep

Autor: Armonth | El jueves 28 de diciembre del 2006 @ 13:00.

El interprete de comandos de un Unix -- a.k.a consola -- o habitualmente BASH (que sí: hay otras terminales aparte de bash pero es casi un estándar actualmente) siempre se le ha atribuido un potencial enorme y no es ninguna mentira. Encadenando comandos (programas) se pueden llegar a hacer scripts bastante complejos que a menudo incluso nos sirven de sustitutos de programas más tradicionales.

Sin llegar a niveles altos (el shell scripting y todo lo que huela a programación me supera por falta de tiempo) uno se da cuenta que jamás le sacara todo el jugo y potencial.

Un ejemplo lo tenemos en dos programas de lo más sencillo: cat y grep. El primero saca por pantalla el contenido de un fichero y el segundo se puede usar para mostrar líneas que coincidan con un patrón (o al revés: las que no coincidan).

Hasta ahí nada particular, hace tiempo me metieron la primera en la frente con un comentario que decía algo así:

Acabas de ganar el Cat Useless Award por este uso del cat.

¿Qué hice? pues la siguiente orden:

cat fichero | grep patrón

Con el noble objetivo de mostrar por pantalla todas las líneas que encajaran con patrón dentro de fichero. Debería haber usado:

grep patrón fichero

¿La diferencia? Un cat y un pipe menos por un lado. Por el otro es más óptimo y rápido:

$ time cat fichero | grep patrón

real 0m0.049s  
user 0m0.048s  
sys 0m0.030s

$ time grep patrón fichero

real 0m0.027s  
user 0m0.024s  
sys 0m0.010s

A mayor es el fichero más se nota la diferencia. Cuando hablamos de un grep no tiene mayor importancia pero cuando son shellscripts complejos o algo que deba procesar muchos datos la cosa puede cambiar.

Esto fue hace tiempo, ahora viene la "versión 2.0": usar grep y wc -l para saber cuántas líneas coinciden con un patrón es otra manera de desperdiciar tiempo de proceso:

$ time grep patrón fichero | wc -l  
6320

real 0m0.196s  
user 0m0.018s  
sys 0m0.063s

En su lugar, mejor usar grep con el parámetro -c:

$ time grep -c patrón fichero  
6320

real 0m0.026s  
user 0m0.009s  
sys 0m0.015s

Este caso ya sangra más: ocho veces más rápido el segundo ejemplo que el primero, o en patrones pequeños (5-20 resultados) 2.5 veces más rápido.

Con estos simples ejemplos me doy cuenta que la manera más simple no siempre es la más óptima.

El día que me meta finalmente en la programación (nada de editar cosas: hacerlas desde cero) creo que voy a convertirme en un devorador de artículos sobre optimización.

Comentarios