Información blog

Linux, tutoriales, noticias, sistemas, redes y seguridad informática, entre otras cosas.

lunes, 23 de marzo de 2015

grep, egrep y fgrep. ¿Qué diferencia hay entre éstos?

Grep es una de las herramientas más usadas en el mundo del mundo del software libre. Cualquiera, desde el principiante que empieza a jugar con la consola, hasta el más veterano, usa esta herramienta casi sin darse cuenta. ¿Quien no ha escrito alguna vez ls -la |grep "lo_que_sea"? Para aquel que este concepto le sea ajeno; grep es una herramienta que utiliza expresiones regulares para realizar consultas. Ésto es realmente útil cuando te encuentras con una gran variedad de archivos y sólo desea visualizar aquellos que tengan un patrón en particular: una extensión en concreto, que comiencen sólo por una letra que nosotros queremos, etc...



Dicha herramienta viene de forma nativa en todas las distribuciones Linux, y es generalmente usado en la consola cómo si fuese un comando o un parámetro. En caso de ir cómo comando se suele usar para realizar un filtrado general de todo lo que va encontrando. Por ejemplo para buscar todo lo que contenga la cadena que nosotros deseemos habría que poner:

grep "lo_que_sea" *

El * significa que busca todos los archivos que se encuentran el posición actual. El resultado que mostraría todos los ficheros y directorios que contengan el nombre "lo_que_sea" y todos el contenido "lo_que_sea" que haya en los ficheros.

Si se quisiesen buscar los archivos que NO contengan la que se ha introducido, habría que escribir añadir el parámetro -v tal que así:

grep -v "lo_que_sea" *


Si probáis el resultado de estos dos comandos, veréis que muestra todo de forma muy detallada y que busca incluso dentro de los ficheros, lo cual puede ser útil a veces, pero otras veces sólo nos interesa conocer el nombre de los ficheros y/o directorios sin detalle alguno, ya que con grep a secas hay demasiada información innecesaria. Debido a dicha necesidad existe el parámetro -l.


grep -l "lo_que_sea" *

Imaginemos que poseemos serie de patrones que hemos almacenado en un fichero y que queremos usar esos patrones para realizar una consulta en otro fichero. Es decir tenemos un fichero por ejemplo con tres líneas: la primera pone carne, la segunda pescado y la tercera verdura. Queremos ver si hay líneas en otro fichero que posean alguna de esas tres líneas; el parámetro -f nos permite hacerlo:

grep -f fichero_patrones.txt fichero_a_consultar.txt

Por último está el parámetro -r; el cual toma en cuenta el contenido de los directorios para realizar las búsquedas. Éste viene muy bien si nos encontramos en una ruta que contiene muchas carpetas y queremos revisar éstas sin tener que entrar dentro de éstas una por una. En algunas versiones puede que -r no funcione y tenga que usarse -F en su lugar:

grep -r "lo_que_sea" *

Ahora bien, aún cuando esto es muy útil, lo más común suele ser que lea la un comando introducido anteriormente y filtre el resultado. Para ello se introduce el comando deseado y se le añade |grep (parámetros) "lo_que_sea". En caso de querer usar éste método para grep, hay que tener en cuenta que no se puede usar el parámetro -l .Pongamos cómo ejemplo el famoso ls y cómo parámetro a buscar, todo aquello que empiece por a:

ls |grep "^a"

o todo aquello que contenga una a:

ls |grep a

o todo aquello que no contenga una a:

ls |grep -v a


o una expresión más compleja del tipo:


ls |grep -v "ae*" --> Esto sería lo mismo que decir que consulte todo aquello que no empiece por a seguido de una e más cualquier carácter o caracteres (entre uno e infinito).

Con esto uno tendría conocimiento sobre grep y en la mayoría de los casos, sería suficiente. Pero no siempre. Hay veces que uno se ve en la situación de que por la necesidad de la situación o porque se lo exigen, tiene que usar variantes de grep, variantes cuyas diferencias con el grep original son ligeras, pero significativas. Las variantes más famosas son egrep (Enhanced grep) y fgrep (Fixed-string), y aunque lo más común es usar el grep original, sería un error desestimar estas dos opciones.

Egrep


Comencemos con egrep. Esta variante es una versión más completa que el grep original, que mantiene las funcionalidades originales y además le añade unas nuevas. Esta herramienta es muy útil para realizar consultas avanzadas que grep por sí sólo no es capaz de realizar. Egrep es lo equivalente a grep -E, el cual no he explicado antes para tener la explicación mejor estructurada. Egrep acepta algunos símbolos que grep de por sí no acepta; Revisemos cada uno de éstos:


+ --> El carácter que le precede debe de coincidir una vez o más en la busqueda: egrep "poll+" fichero o directorio.

? --> El carácter que le precede es completamente opcional y coincide al menos una vez; Eso viene bien si por ejemplo se desea consultar un patrón y queremos que el último carácter sea cualquiera ya sea que exista o no, tal que así: egrep "poll?" fichero o directorio.

| --> Permite poner varios patrones de búsqueda tal que así egrep "pollo | pavo" "fichero o directorio". Esto buscaría todo aquello que coincidiese con pollo o pavo.

{} --> El carácter que le precede a este símbolo debe de aparecer un número determinado de veces que debe de ser determinado entre los {}. También puede ponerse un rango de número de apariciones. Esto puede parecer lioso así escrito con lo que lo mejor es mostrar unos ejemplos en los que las letras n y m que voy a poner son números aleatorios. IMPORTANTE: n y m siempre son números.:

       {n} --> El carácter que le precede aparece exactamente n veces.
       {n,} --> El carácter que le precede aparece cómo mínimo n veces.
       {n,m} --> El carácter que le precede debe aparecer n veces cómo mínimo y m veces cómo máximo.

Unos ejemplo más especifico podría ser éste:

cat fichero |egrep "C{1,5}ambios" --> Buscara todo aquello que contenga la palabra ambios y que la letra que le precede sea la C que debe aparecer entre 1 y 5 veces.

Fgrep

"Fixed-string grep", conocido erróneamente por muchos cómo "Fast grep", es una variante más veloz que grep pero que cómo contrapartida sólo puede buscar cadenas fijas (sin expresiones regulares, sólo la cadena). Cuando sólo se usa una cadena cómo patrón de búsqueda no se nota mucha diferencia, en cambio si se usa un gran número de patrones la diferencia es muy significativa.

fgrep "hola" /etc/ --> Válido
fgrep -f fichero_patrones fichero_a_consultar.txt --> Válido y mucho más veloz que grep -f
fgrep "ae*" --> Inválido


Con esto espero que tengáis un poco más claras las diferencias fundamentales entre cada tipo de grep.

Saludos.

2 comentarios :

  1. "grep -f fichero_patrones.txt fichero_a_consultar.txt", hombre, la verdad es que nunca se termina de aprender, no tiene idea de lo que pasé para conseguir ese mismo proposito en con un script de shell, y así, con una sola linea ... mil gracias

    ResponderEliminar
    Respuestas
    1. Muchas gracias por tus palabras.

      Entiendo perfectamente la situación que describes; te rompes la cabeza para conseguir un propósito en concreto y haces mil pruebas cuando la solución es mucho más sencilla. A veces estas cosas pueden parecer muy "geek", pero lo cierto es que estas curiosidades pueden salvarte la vida en algunos momentos determinados.

      ¡Saludos!

      Eliminar