Búsqueda dentro de textos

Grep

Ya hemos visto como podemos realizar búsquedas de ficheros con una amplia variedad de opciones. Sin embargo, a menudo es necesario también buscar dentro de un fichero (normalmente en ficheros de texto). Para ello podemos utilizar el comando grep.

Informalmente, podemos ver el uso del comando de la siguiente forma:

grep <opciones de búsqueda> <cadena de texto a buscar> <ficheros>

Las opciones son optativas y aunque la especificación de la cadena de texto a buscar admite descripciones muy complejas es posible utilizar grep de forma tan sencilla como sigue:

$ grep Calzado telefonos.txt
Carlos Calzado 5550178

En este ejemplo hemos buscado la cadena «Calzado» en el listado de teléfonos que hicimos en un ejercicio anterior y grep nos devuelve la línea del texto donde la encuentra. Esto puede resultar de gran utilidad si manejamos un fichero con un gran volumen de información.

Podemos incluir más de un fichero en la búsqueda, como en el siguiente ejemplo:

$ grep Calzado telefonos.txt telef-may.txt
telefonos.txt:Carlos Calzado 5550178

Vemos que ahora la salida incluye el nombre del fichero donde se ha encontrado la cadena. Es interesante también comprobar que no la ha encontrado en el segundo fichero. La razón es que este último contiene los nombres en mayúsculas. Para indicarle al comando que no nos importa si la cadena está en mayúsculas o minúsculas podemos usar la opción -i como sigue:

$ grep -i Calzado telefonos.txt telef-may.txt
telefonos.txt:Carlos Calzado 5550178
telef-may.txt:CARLOS CALZADO 5550178

A veces puede interesarnos simplemente saber en cuántas líneas de un fichero se encuentra la cadena. Para ello podemos usar la opción -c combinada con la anterior:

$ grep -ic Luis telefonos.txt telef-may.txt
telefonos.txt:2
telef-may.txt:2

Asimismo podemos también buscar líneas que no contengan una cadena. Siguiendo el ejemplo anterior, podemos buscar las líneas que no contienen ‘Luis’ usando la opción -v:

$ grep -iv Luis telef.may.txt
MATEO GUERRICER 5559082
GEMA PELLON 5558727
CARLOS CALZADO 5550178

Entubando greps

La utilidad del comando grep se muestra especialmente cuando se combina con otros comandos. Como hemos visto con anterioridad una forma de hacerlo es usando ‘tuberías’.  Para ello hay que recordar los conceptos de entrada y salida estándar que vimos y considerar que la salida de un comando puede verse como un fichero.

Por ejemplo, si listamos utilizando la opción -l los ficheros del directorio /var/log/ que guarda registros de actividad del sistema obtendremos una salida como la siguiente:

$ ls -l /var/log
total 5176
drwxr-x--- 2 root root    4096 Feb 18 17:16 audit
-rw------- 1 root root     972 Mar 26  2012 boot.log
-rw------- 1 root utmp 2198784 Feb 22 06:12 btmp
-rw------- 1 root utmp    2688 Apr 18  2012 btmp-20130208
...

Supongamos que nos interesan sólo los ficheros normales (no directorios) y del grupo ‘utmp’. Si vemos esta salida como un fichero, la solución podría ser utilizar el comando grep especificando que busque la cadena ‘utmp’ y que compruebe que no hay una ‘d’ al principio de la línea.

Comenzando por la primera condición, escribiremos lo siguiente:

$ ls -l /var/log | grep utmp

El resultado es el conjunto de líneas del listado que contienen ‘utmp’. Utilizando el símbolo ‘|’, como habíamos visto, redireccionamos la salida del primer comando al segundo. Ahora podemos añadir otro comando grep para especificar la segunda condición:

$ ls -l /var/log | grep utmp| grep -v ^d

El símbolo ‘^’ antes de la cadena a buscar indica que debe estar situada al principio de la línea, que es exactamente lo que nos interesa. Como resultado tenemos el listado resultante del encadenamiento anterior, pero sin directorios.

Finalmente, podemos ilustrar la utilidad de la redirección para resultados demasiado largos para ver en pantalla o que deseamos conservar:

$ ls -l /var/log | grep utmp| grep -v ^d > lista-adm.txt

Ten en cuenta que no se especifica ninguna opción para la posición de la cadena ‘utmp’, por lo que grep puede devolver no sólo los ficheros de dicho grupo, sino cualquier línea del listado que contenga el texto.

Prueba a combinar el comando find y el comando grep para buscar cadenas de texto dentro de un listado de ficheros que cumplen unos criterios de búsqueda.