Grep

En esta parte de la guía estudiaremos la herramienta grep. Al igual que la parte de regex, este tutorial tiene un enfoque general, sin aplicaciones en Bioinformática (lo que veremos más adelante).

Nota importante

En la mayoría de secciones existen preguntas y pequeños ejercicios, marcados con la etiqueta Pregunta, cuyas respuestas deben ser realizadas como deber de esta parte del curso. Debes guardar las respuestas en el Jupyter notebook que debes entregar en este capítulo y correr los comandos en las preguntas que esto sea posible.

En la última parte de este capítulo se encuentran las repuestas de los ejercicios, pero te recomendamos que primero trates de resolverlos por tu cuenta.

Advertencia

En este tutorial usaremos la herramienta GNU grep, que viene instalada por defecto en la mayoría de distribuciones de GNU/Linux. Puede que algunos de los comandos usados con esta herramienta no sean compatibles con otras versiones del programa usadas en MacOS, por lo que les recomendamos instalar GNU grep. En este blog se discute este tema.

Archivo para este tutorial

En este tutorial usaremos un archivo que tiene la versión completa de la canción Contrapunto para Humano y Computadora de la banda El Cuarteto de Nos.

Nota

Pueden encontrar este archivo en este link dentro del repositorio de GitHub del libro.

¿Qué es grep?

Grep es una herramienta de SOs basados en UNIX, que permite hacer búsquedas de regex en archivos de texto o entradas estándar - stdin derivados de piping (que veremos en detalle en una sección posterior), e imprimir la o las líneas que coincidan con el o los patrones buscados. Un aspecto que se debe considerar es que dado que el caracter de nueva línea \n es un separador de la lista de patrones, no hay forma de buscar los caracteres de nueva línea usando grep.

La sintaxis general de esta herramienta es de la siguiente forma:

grep [-opcion(es)...] ["patron(es)"...] [archivo(s)]

Pueden existir cero o más opciones y archivos. Si no se provee ningún archivo grep busca en el directorio de trabajo actual si se le da una opción de línea de comandos que especifique la recursividad; de lo contrario, busca en el (stdin). Además, se deben proveer uno o más patrones que son separados internamente por el programa por caracteres \n.

Tip

Normalmente, los patrones se ponen entre comillas cuando se usa grep para evitar la interpretación y expansión de los meta-caracteres por la shell.

Diferentes versiones de grep: -G -E -F -P

En GNU grep existen cuatro versiones de la herramienta, que se eligen con diferentes opciones:

Versión

Descripción

-G o --basic-regexp

Interpreta los patrones como regex básicas (BREs). Es las versión estándar de la herramienta

-E o --extended-regexp

Interpreta los patrones como regex extendidas (EREs)

-F o --fixed-strings

Interpreta los patrones como string fijos, no como regex

-P o --perl-regexp

Interpretar los patrones como expresiones regulares compatibles con Perl (PCREs)

Nota

En la implementación GNU grep no hay diferencia funcional entre las sintaxis de expresión regular básica y extendida. La única diferencia es que en las expresiones regulares básicas los meta-caracteres ? + { | () se interpretan como caracteres literales y por tanto se deben escapar con \.

Por ejemplo, usemos el siguiente comando para buscar las líneas que tengan los caracteres a o e usando el meta-caracter de alternancia | con la versión estándar:

grep "a|e" Contrapunto_para_Humano_y_Computadora_Cuarteto_de_Nos.txt

Pregunta

Ahora, intenten correr el mismo comando añadiendo la opción -E. ¿Cambió la respuesta en comparación con el comando con la versión estándar?

Noten que para que este comando funcione debes estar en el directorio _files, o especificar el path completo del archivo desde el directorio en el que se encuentren.

Para evitar complicaciones, si usamos regex que incluyan patrones con el meta-caracter de alternancia, agrupamiento o cuantificadores, se usa la versión extendida -E.

Opciones de la herramienta grep

Información general del programa: --version, --help

El comando --version o -V se usa para imprimir en la terminal el número y algunas características de la versión de grep instalada en el SO; mientras que --help sirve para imprimir información general del uso y las opciones de grep.

Pregunta

¿Cuál versión de grep tienes en tu SO?

Flags: -e -f -i -v -w -x

En GNU grep existen los siguientes modos para controlar las coincidencias:

Flag

Descripción

-e "patron(es)" o --regexp="patron(es)"

Busca los patrones especificados como argumento y los caracteres \n separan un patrón del siguiente

-f archivo o --file=archivo

Busca los patrones de un archivo, uno por línea

-i o --ignore-case

Hace que la regex no sea sensible a mayúsculas o minúsculas. La regex «abc» coincide con el patrón «AbC»

-v o --invert-match

Invierte el sentido de coincidencia, para seleccionar líneas que no coinciden con el patrón

-w o --word-regexp

Selecciona solo las líneas que contengan coincidencias que formen palabras completas

-x o --line-regexp

Seleccione solo los patrones que coincidan exactamente con toda la línea

Entonces, si queremos buscar las líneas del archivo de trabajo que tengan la palabra computadora utilizamos el siguiente comando:

grep "computadora" Contrapunto_para_Humano_y_Computadora_Cuarteto_de_Nos.txt

Pregunta

Si observamos el archivo, vemos que hay ciertas líneas que tienen la palabra computadora pero empiezan con C mayúscula. ¿Cómo debemos modificar el comando previo para realizar esta búsqueda?

Si queremos buscar las líneas que contengan la palabra computadora o Roberto sin importar las mayúsculas o minúsculas, podríamos usar la regex computadora|Roberto con la opción -i y la versión -E, pero otra opción sería usar un archivo con las dos palabras y usar una opción adicional. ¿Cuáles comandos usarías para crear el archivo de patrones por consola y realizar esta búsqueda usando el archivo que creaste?

¿Coincidieron los resultados de los dos comandos?

Ahora, busquen las líneas que contengan el patrón se con y sin la opción -w, ¿Hay diferencia en los resultados con estos comandos?

Siguiendo el mismo principio, busquen las líneas con el patrón Ni con y sin la opción -x, ¿Hay diferencia en los resultados con estos comandos?

Y, ¿Cómo hacemos para buscar las líneas que no tengan los patrones computadora o Roberto sin importar las mayúsculas o minúsculas?

Control general de salida: -c --color -L -l -m -o -q -s

Se tienen las siguientes opciones para controlar la salida de forma general:

Opción

Descripción

-c o --count

Se imprime el número de líneas que coinciden con un patrón para cada archivo de entrada. Con la opción -v se cuentan las líneas que no coinciden

--color

Se colorean los patrones, líneas coincidentes o de contexto, nombres de archivo, y números de línea

-L o --files-without-match

Se imprime el nombre de los archivos de entrada que no coinciden con el patrón de búsqueda

-l o --files-with-matches

Se imprime el nombre de los archivos de entrada que coinciden con el patrón de búsqueda

-m num o --max-count=num

La búsqueda del patrón se detiene luego de que se cumpla con el número de coincidencias especificadas en num

-o o --only-matching

Se imprime solo las partes coincidentes con el patrón de búsqueda de las líneas, con cada parte separada por una nueva línea

-q o --quiet

No se imprime nada en la terminal

-s o --no-messages

Suprimir los mensajes de error de los resultados que se imprimen en la terminal

Pregunta

Ahora, considerando estos conocimientos y lo que hemos aprendido previamente sobre regex, ¿Qué comando podemos usar para verificar el número de versos de la canción, incluyendo la discusión final entre Roberto y la computadora como otro verso?

¿Cuál(es) comandos usarías para determinar el número de versos de la computadora, Roberto y de ambos?

Tip

Por defecto, la mayoría de versiones de GNU grep tienen establecido el color del resultado de las coincidencias del comando con rojo y fondo negro, pero esto se puede cambiar usando la variable de ambiente GREP_COLORS. Pueden encontrar más información sobre este tema en el siguiente blog.

Pregunta

Utilizando la opción -m de 4, ¿Cuál es la última línea que se imprime buscando el patrón ? ?

El uso de las opciones -ly -L lo veremos más adelante en este tutorial, y les pedimos que prueben el funcionamiento de las opciones -o, -q y s por su cuenta.

Control de prefijo de línea de salida : -H -h -n -T

Para controlar el prefijo de línea se tienen las siguientes opciones:

Opción

Descripción

-H o --with-filename

Imprime el nombre de archivo por cada coincidencia. Este es el valor predeterminado cuando hay más de un archivo para buscar

-h o --no-filename

Suprima el prefijo de los nombres de archivo. Este es el valor predeterminado cuando solo hay un archivo para buscar

-n o --line-number

Imprime el número de línea de cada coincidencia antes del patrón

-T o --initial-tab

Se verifica de que el primer carácter del contenido de la línea tiene en una tabulación

Pregunta

Ahora, si queremos conocer el número de línea de todas las líneas que terminen en una palabra con los sufijos ando, ión, u ono; ¿Qué comando podría usar que cumpla con este criterio de búsqueda?

¿Cuántas líneas hay con palabras que terminen con cada uno de estos sufijos. Prueba el mismo comando con la opción -T,

¿Hay alguna diferencia con lo que obtuviste previamente?

El uso de las opciones -hy -H lo veremos más adelante en este tutorial.

Control de contexto de línea: -A -B -C

Se puede controlar la impresión del contexto de línea con las siguientes alternativas:

Opción

Descripción

-A num o --after-context=num

Imprime el número de líneas que se ubican después de las coincidencias con el patrón de búsqueda

-B num o --before-context=num

Imprime el número de líneas que se ubican antes de las coincidencias con el patrón de búsqueda

-C num o --context=num

Imprime el número de líneas que se ubican antes y después de las coincidencias con el patrón de búsqueda

Pregunta

Utilizando las opciones de contexto de línea, determina los límites de los versos 3, 5, 10, y 12, ¿Cuántas líneas componen a cada uno de estos versos omitiendo su título correspondiente?.

Aisla estos cuatro versos (incluyendo su título) en archivos separados con nombre verso#.txt solamente usando la terminal, siendo # el número del verso respectivo, y ubícalos en el directorio archivos ¿Cuál es un ejemplo de uno de los comandos que usaste para esta tarea?

Selección de archivos o directorios: -r --exclude=glob --include=glob

Las opciones de selección de archivos o directorios más comunes son:

Opción

Descripción

-r o --recursive

Para cada operación que se aplique al directorio, lea y procese todos los archivos en ese directorio, de forma recursiva

--exclude=glob

Omitir cualquier archivo de línea de comandos con un sufijo de nombre que coincida con el patrón global, utilizando coincidencias con wildcards

--include=glob

Buscar solo archivos de línea de comandos con un sufijo de nombre que coincida con el patrón global, utilizando coincidencias con wildcards

Pregunta

Ahora, si queremos verificar cuáles documentos del directorio archivos tienen una línea que contenga la palabra computadora, sin importar las mayúsculas y minúsculas, podemos utilizar las opciones -r y -l. ¿Cuáles archivos cumplen con esta condición?.

Si en lugar de la opción -l usas -L, ¿Qué archivos aparecen ahora?.

Prueba el mismo comando con las opciones -H y -h, ¿Cuáles fueron las diferencias con los resultados previos?

Material suplementario

La mayoría de los contenidos de esta parte se obtuvieron de la documentación oficial de GNU, que pueden acceder con el siguiente link. En los siguientes enlaces pueden encontrar información adicional sobre este tema: