grep: filtrado de texto en streams y archivos

grep busca líneas que coinciden con un patrón dentro de un archivo o de lo que le llegue por la entrada estándar, y devuelve solo esas líneas. El nombre viene de g/re/p, un comando del editor ed que hacía exactamente eso: global regular expression print. Esa genealogía explica por qué grep trabaja línea a línea y por qué usa expresiones regulares por defecto, concretamente el dialecto BRE (Basic Regular Expressions), que es el más antiguo y conservador.

El diseño tiene una lógica clara: grep no modifica nada, solo filtra. Recibe texto, aplica un patrón, y emite las líneas que coinciden. Eso lo hace ideal tanto para buscar dentro de archivos estáticos como para actuar de filtro dentro de un pipe, encadenado con otras herramientas. Úsalo cada vez que necesites encontrar algo en un archivo de configuración, en logs, o en la salida de cualquier comando. Si lo usas mal, el riesgo más común no es romper nada (recuerda: solo lee), sino obtener falsos negativos porque el patrón no era lo que creías, o falsos positivos porque era demasiado amplio.

Las opciones que vas a usar el noventa por ciento del tiempo son estas: -i para ignorar mayúsculas y minúsculas, -v para invertir la búsqueda (líneas que no coinciden), -n para ver el número de línea, -r para buscar de forma recursiva en un directorio, -l para que solo te diga qué archivos contienen el patrón, -c para contar cuántas líneas coinciden, y -A/-B/-C para ver contexto alrededor del match. Cuando el patrón contiene caracteres como +, ?, | o paréntesis agrupadores, necesitas -E (Extended Regular Expressions) o su alias egrep, porque BRE no los entiende de la misma manera. Y si buscas una cadena literal sin ningún tipo de metacarácter, -F desactiva la interpretación de regex y es notablemente más rápido.

# Archivo de log de ejemplo con el que vamos a trabajar
# (en un sistema real usarías /var/log/syslog o similar)
grep -n "error" /var/log/syslog

# Lo mismo pero sin importar si es "Error", "ERROR" o "error"
grep -in "error" /var/log/syslog

# Líneas que NO mencionan "error": útil para limpiar ruido
grep -iv "error" /var/log/syslog

# Ver 3 líneas de contexto alrededor de cada match:
# -B 3 antes, -A 3 después, o -C 3 para ambos a la vez
grep -C 3 "Connection refused" /var/log/syslog

# Contar cuántas veces aparece "warning" (sin distinguir mayúsculas)
grep -ic "warning" /var/log/syslog

# Buscar recursivamente en /etc qué archivos mencionan "PermitRootLogin"
# -r entra en subdirectorios, -l muestra solo nombres de archivo
grep -rl "PermitRootLogin" /etc

# Buscar en varios archivos a la vez con -n para saber la línea exacta
grep -n "listen" /etc/nginx/nginx.conf /etc/nginx/sites-enabled/*

# grep como filtro en un pipe: ver solo las líneas de error del journal
# journalctl vuelca texto plano, grep filtra igual que con un archivo
journalctl -b | grep -i "failed"

# Con -E activamos ERE: el | significa "o", + significa "uno o más"
# Buscamos líneas que contengan "error" o "critical" (case insensitive)
grep -Ei "error|critical" /var/log/syslog

# -F: búsqueda de cadena literal, sin interpretar metacaracteres
# Útil cuando el patrón contiene puntos, corchetes, paréntesis, etc.
# Aquí buscamos la IP literalmente, sin que el punto sea "cualquier carácter"
grep -F "192.168.1.1" /var/log/nginx/access.log

# Número de línea + contexto + recursivo: combinación habitual al depurar
grep -rn -A 2 "segfault" /var/log/

Fíjate en la línea de journalctl -b | grep -i "failed": journalctl vuelca el log del arranque actual como texto por su salida estándar, y grep lo recibe por su entrada estándar exactamente igual que si fuera un archivo. No hay ninguna diferencia interna para grep. Esta transparencia es la base de la filosofía Unix de pipes, y es lo que hace que grep sea tan universal.

La línea grep -rl "PermitRootLogin" /etc merece atención. Con -r solo obtendrías todas las líneas que coinciden en todos los archivos de /etc, que puede ser mucho ruido. Añadir -l cambia el comportamiento: grep para en cuanto encuentra una coincidencia en cada archivo y solo imprime el nombre. Es más rápido y más legible cuando lo que necesitas es saber dónde está algo, no ver todas las ocurrencias.

En grep -F "192.168.1.1" el punto en una expresión regular BRE significa “cualquier carácter”, así que sin -F el patrón 192.168.1.1 también coincidiría con 192.168.111 o 192A168B1C1. Con -F lo que escribes es exactamente lo que se busca, sin interpretación. Úsalo siempre que el patrón provenga de una variable del shell o de entrada de usuario, para evitar sorpresas.

La combinación -Ei "error|critical" muestra por qué necesitas -E: el carácter | en BRE es literal, no significa “o”. Con -E activas ERE y | funciona como alternativa entre expresiones. Lo mismo aplica a + (uno o más) y ? (cero o uno), que en BRE hay que escapar como \+ y \?, mientras que con -E los usas directamente.

Para búsquedas en repositorios de código o proyectos con muchos archivos, ripgrep (rg) es una alternativa que vale la pena conocer. Es significativamente más rápido que grep -r en directorios grandes, respeta automáticamente los patrones de .gitignore, y colorea el output por defecto. Se instala con apt install ripgrep y su sintaxis básica es idéntica: rg "patrón" directorio/. No reemplaza a grep en pipes ni en scripts de sistema, donde grep siempre va a estar disponible, pero para explorar código fuente es mejor herramienta.

44

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scroll al inicio