Grep: buscando padrões em arquivos

1. Introdução ao Grep e sua sintaxe básica

O comando grep é uma das ferramentas mais poderosas e essenciais no arsenal de qualquer usuário de Bash/Shell Script. Seu nome deriva do comando g/re/p (global/regular expression/print) do editor ed, e sua função principal é buscar padrões em arquivos ou na saída de outros comandos, retornando as linhas que correspondem ao padrão especificado.

A sintaxe fundamental do grep é simples e direta:

grep [opções] padrão [arquivo...]

Historicamente, existiam três variações do comando: grep (básico), egrep (expressões regulares estendidas) e fgrep (busca literal, sem interpretação de metacaracteres). Nas versões modernas do GNU grep, essas funcionalidades foram unificadas: use grep -E no lugar de egrep e grep -F no lugar de fgrep. O grep padrão ainda utiliza expressões regulares básicas (BRE).

2. Padrões básicos e curingas

A busca mais simples envolve strings literais. Para buscar a palavra "erro" em um arquivo de log:

grep "erro" /var/log/syslog

O uso de aspas simples ou duplas é recomendado para evitar que o shell interprete caracteres especiais. Aspas simples preservam o conteúdo literalmente, enquanto aspas duplas permitem expansão de variáveis.

Os metacaracteres básicos do grep incluem:

  • . (ponto): corresponde a qualquer caractere único
  • *: corresponde a zero ou mais ocorrências do caractere anterior
  • ^: ancora o padrão ao início da linha
  • $: ancora o padrão ao final da linha

Exemplos práticos:

# Linhas que começam com "ERROR"
grep "^ERROR" arquivo.log

# Linhas que terminam com "falhou"
grep "falhou$" arquivo.log

# Linhas que contêm "casa" ou "caso" (casa, caso, cas? )
grep "cas." arquivo.txt

3. Expressões regulares estendidas com grep -E

O modo de expressões regulares estendidas (ERE) com grep -E oferece metacaracteres adicionais que tornam as buscas muito mais expressivas:

  • +: uma ou mais ocorrências do caractere anterior
  • ?: zero ou uma ocorrência do caractere anterior
  • {n,m}: de n a m ocorrências
  • |: alternância (ou)
  • ( ): agrupamento

Classes de caracteres também são amplamente utilizadas:

# Buscar "abc" ou "xyz"
grep -E "abc|xyz" arquivo.txt

# Telefones com formato (XX) XXXX-XXXX
grep -E "\([0-9]{2}\) [0-9]{4}-[0-9]{4}" contatos.txt

# Palavras com 3 a 5 letras
grep -E "\b[a-zA-Z]{3,5}\b" texto.txt

# Linhas que contêm dígitos repetidos
grep -E "([0-9])\1" numeros.txt

4. Opções essenciais de linha de comando

O grep oferede diversas opções que controlam a saída e o comportamento da busca:

# Contagem de linhas correspondentes
grep -c "padrão" arquivo.txt

# Numeração das linhas
grep -n "erro" log.txt

# Apenas o trecho que corresponde (não a linha inteira)
grep -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" ips.txt

# Inversão: linhas que NÃO correspondem
grep -v "^#" config.conf

# Contexto: linhas antes (-A), depois (-B) ou ambos (-C)
grep -C 3 "FATAL" sistema.log
grep -A 2 "exceção" trace.log

# Ignorar maiúsculas/minúsculas
grep -i "warning" mensagens.log

# Busca recursiva em diretórios
grep -r "TODO" /home/projeto/src/

5. Grep em combinação com pipes e redirecionamentos

O verdadeiro poder do grep emerge quando combinado com outros comandos via pipes (|):

# Filtrar processos em execução
ps aux | grep "nginx"

# Buscar em múltiplos arquivos e redirecionar resultado
grep -rn "debug" /var/log/ > resultados.txt

# Encadear buscas complexas
dmesg | grep -i "error" | grep -v "usb" | head -20

# Usar com xargs para processar resultados
grep -l "config" *.txt | xargs wc -l

Exemplo prático: encontrar todos os arquivos PHP que contêm uma função específica:

grep -rl "function validar_email" /var/www/html/ | xargs -I{} cp {} ./backup/

6. Expressões regulares avançadas e classes POSIX

As classes POSIX oferecem uma maneira portável de referenciar conjuntos de caracteres:

  • [:alpha:]: letras alfabéticas
  • [:digit:]: dígitos 0-9
  • [:space:]: espaços, tabs, newlines
  • [:punct:]: pontuação
  • [:alnum:]: alfanumérico
  • [:upper:] / [:lower:]: maiúsculas / minúsculas

Âncoras de palavra com \< e \> permitem buscar palavras completas:

# Buscar apenas "cor" como palavra inteira, não "correr" ou "disco"
grep "\<cor\>" dicionario.txt

# Validar formato de e-mail (simplificado)
grep -E "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$" emails.txt

# Validar IPs
grep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}$" ips.txt

# Usando classes POSIX para buscar apenas letras maiúsculas
grep "^[[:upper:]]" linhas.txt

7. Boas práticas e armadilhas comuns

Alguns cuidados são essenciais ao usar grep:

1. Metacaracteres em busca literal: Se você precisa buscar um ponto literal (.), use grep -F ou escape o caractere:

# Buscar literalmente "versao 2.0"
grep -F "versao 2.0" changelog.txt

2. Arquivos binários: O grep pode interpretar arquivos binários incorretamente. Use -a para forçar tratamento como texto ou -I para ignorar binários:

grep -I "padrão" *

3. Performance: Para arquivos muito grandes, considere alternativas como ripgrep (rg) ou ag (The Silver Searcher), ou use indexação com grep -r com cautela.

4. Cuidado com padrões muito genéricos: grep -r "." / pode travar seu sistema. Sempre restrinja o escopo da busca.

5. Use -l e -L para listar arquivos: Quando você só precisa saber quais arquivos contêm (ou não) o padrão:

# Arquivos que contêm "TODO"
grep -rl "TODO" .

# Arquivos que NÃO contêm "licença"
grep -rL "licença" . --include="*.py"

O grep é uma ferramenta indispensável para análise de logs, busca em código-fonte, processamento de texto e automação de tarefas no shell. Dominar suas opções e expressões regulares eleva significativamente sua produtividade como desenvolvedor ou administrador de sistemas.

Referências