Usuários Linux de longa data certamente estão familiarizados com o grep
, também conhecido como Global Regular Expression Print. Esta ferramenta de processamento textual é crucial para buscas em arquivos e diretórios, e se mostra extremamente valiosa para quem domina o sistema. Entretanto, o uso do grep
sem expressões regulares (regex) pode limitar seu potencial.
Mas, afinal, o que são Regex?
Regex, ou expressões regulares, são padrões que expandem as capacidades de pesquisa do grep
. Em essência, regex são mecanismos avançados de filtragem de resultados. Com a prática, você será capaz de utilizar regex eficientemente, inclusive em conjunto com outros comandos Linux.
Neste guia, exploraremos como usar o grep
e o regex de maneira eficaz.
Pré-requisitos
Para dominar o uso do grep
com regex, é necessário ter um bom conhecimento do sistema Linux. Se você é um iniciante, nossos guias introdutórios sobre Linux podem ser úteis.
Você também precisará de um computador com sistema operacional Linux. Qualquer distribuição Linux servirá, e se você utiliza Windows, o WSL2 permite executar o Linux. Temos um guia detalhado sobre o WSL2 que você pode conferir.
O acesso à linha de comando ou terminal é essencial para executar os comandos apresentados neste tutorial sobre grep
/regex.
Além disso, é necessário ter pelo menos um arquivo de texto para executar os exemplos. Para este guia, utilizei o ChatGPT para gerar um texto sobre tecnologia, pedindo que repetisse os nomes das tecnologias. O prompt utilizado foi:
“Gere 400 palavras sobre tecnologia. Inclua a maior parte da tecnologia possível. Além disso, repita os nomes das tecnologias no texto.”
Com o texto gerado, copiei e salvei em um arquivo chamado tech.txt
, que usaremos nos exemplos a seguir.
Por fim, é indispensável ter uma compreensão básica do comando grep
. Para refrescar a memória, você pode consultar nossos 16 exemplos de comandos grep
. Também apresentaremos um breve resumo do comando grep
para iniciarmos.
Sintaxe e Exemplos do Comando grep
A estrutura do comando grep
é simples:
$ grep -opções [regex/padrão] [arquivos]
Como você pode observar, o comando espera um padrão e uma lista de arquivos onde a busca deve ocorrer.
Existem diversas opções para o comando grep
que alteram sua funcionalidade, incluindo:
-i
: Ignora a diferença entre maiúsculas e minúsculas.-r
: Realiza uma busca recursiva em diretórios.-w
: Busca apenas por palavras completas.-v
: Exibe todas as linhas que NÃO correspondem ao padrão.-n
: Exibe o número das linhas que correspondem ao padrão.-l
: Imprime apenas o nome dos arquivos onde há correspondências.--color
: Apresenta a saída com cores.-c
: Mostra a contagem de correspondências para o padrão usado.
#1. Busca por Palavra Inteira
Para buscar uma palavra inteira, utilize o argumento -w
com o grep
. Isso fará com que o comando ignore qualquer sequência de caracteres que contenha o padrão como parte de outra palavra.
$ grep -w ‘tech\|5G’ tech.txt
Como você pode observar, o comando procura por “5G” e “tech” no arquivo tech.txt
, destacando os resultados em vermelho.
Note que o símbolo |
(pipe) precisa ser “escapado” (com a barra invertida \
) para que o grep
não o interprete como um metacaractere.
#2. Busca Ignorando Maiúsculas e Minúsculas
Para realizar uma busca que não diferencia maiúsculas de minúsculas, use o argumento -i
:
$ grep -i ‘tech’ tech.txt
Este comando buscará qualquer ocorrência da sequência “tech”, seja como palavra completa ou como parte de uma palavra, sem se importar com a capitalização das letras.
#3. Busca por Linhas Não Correspondentes
Para exibir todas as linhas que não contêm um determinado padrão, use o argumento -v
:
$ grep -v ‘tech’ tech.txt
O resultado mostrará todas as linhas que não incluem a palavra “tech”, incluindo também as linhas vazias, que geralmente são espaços entre parágrafos.
#4. Busca Recursiva
Para uma busca recursiva, use o argumento -r
com o grep
:
$ grep -R ‘error\|warning’ /var/log/*.log
#output
/var/log/bootstrap.log:2023-01-03 21:40:18 URL:http://ftpmaster.internal/ubuntu/pool/main/libg/libgpg-error/libgpg-erro 0_1.43-3_amd64.deb [69684/69684] -> "/build/chroot//var/cache/apt/archives/partial/libgpg-error0_1.43-3_amd64.deb" [1]
/var/log/bootstrap.log:dpkg: warning: parsing file '/var/lib/dpkg/status' near line 5 package 'dpkg':
/var/log/bootstrap.log:dpkg: warning: parsing file '/var/lib/dpkg/status' near line 5 package 'dpkg':
/var/log/bootstrap.log:dpkg: warning: parsing file '/var/lib/dpkg/status' near line 24 package 'dpkg':
/var/log/bootstrap.log:dpkg: warning: parsing file '/var/lib/dpkg/status' near line 24 package 'dpkg':
/var/log/bootstrap.log:dpkg: warning: ignoring pre-dependency problem!
Neste caso, o comando procura recursivamente pelas palavras “error” e “warning” dentro do diretório /var/log
. Este é um comando útil para identificar alertas e erros em arquivos de log.
grep
e Regex: Definição e Exemplos
Ao trabalhar com regex, você precisa estar ciente de que existem três opções de sintaxe:
- Expressões Regulares Básicas (BRE)
- Expressões Regulares Estendidas (ERE)
- Expressões Regulares Compatíveis com Pearl (PCRE)
Por padrão, o comando grep
utiliza o BRE. Portanto, se você precisar usar outros modos regex, deverá especificá-los. O grep
também trata metacaracteres de maneira literal, então metacaracteres como ?
, +
, )
devem ser “escapados” com a barra invertida \
.
A sintaxe do grep
com regex é a seguinte:
$ grep [regex] [nomes_de_arquivos]
A seguir, veremos exemplos práticos de grep
e regex em ação.
#1. Correspondências Literais de Palavras
Para obter uma correspondência literal de uma palavra, basta fornecer a palavra como regex. Afinal, uma palavra é um regex em si.
$ grep "technologies" tech.txt
Da mesma forma, você pode usar correspondências literais para encontrar usuários que utilizam um determinado shell. Por exemplo:
$ grep bash /etc/passwd
#output
root:x:0:0:root:/root:/bin/bash
nitt:x:1000:1000:,,,:/home/nitt:/bin/bash
Este comando exibirá os usuários que têm acesso ao shell bash.
#2. Correspondência de Âncora
A correspondência de âncora é uma técnica útil para pesquisas avançadas que utilizam caracteres especiais. No regex, existem diferentes caracteres de âncora que você pode usar para representar posições específicas em um texto, incluindo:
- Símbolo de acento circunflexo
^
: Corresponde ao início da string ou linha de entrada, buscando por uma string vazia. - Símbolo de cifrão
$
: Corresponde ao final da string ou linha de entrada, buscando também por uma string vazia.
Outros dois caracteres de correspondência de âncora são o limite de palavra \b
e o limite de não-palavra \B
.
- Limite de palavra
\b
: Permite identificar a posição entre uma palavra e um caractere não-palavra. Em outras palavras, ele permite encontrar palavras completas, evitando correspondências parciais. Você também pode usá-lo para substituir palavras ou contar ocorrências em uma string. - Limite de não-palavra
\B
: É o oposto do\b
, identificando uma posição que não está entre caracteres de duas palavras ou não-palavras.
Vamos analisar alguns exemplos para entender melhor:
$ grep ‘^From’ tech.txt
É importante inserir a palavra ou padrão corretamente, pois o acento circunflexo diferencia maiúsculas e minúsculas. O comando abaixo não retornará nenhum resultado:
$ grep ‘^from’ tech.txt
De maneira semelhante, o símbolo $
pode ser usado para encontrar frases que terminam com determinado padrão, string ou palavra:
$ grep ‘technology.$' tech.txt
Você também pode combinar os símbolos ^
e $
, como no exemplo a seguir:
$ grep “^From \| technology.$” tech.txt
O resultado exibirá as frases que começam com “From” ou terminam com “technology”.
#3. Agrupamento
Para procurar múltiplos padrões de uma vez, use o agrupamento. Ele permite criar pequenos grupos de caracteres ou padrões que são tratados como uma única unidade. Por exemplo, você pode criar um grupo (tech)
que inclua as letras 't'
, 'e'
, 'c'
e 'h'
.
Para exemplificar, observe o comando a seguir:
$ grep 'technol\(ogy\)\?' tech.txt
Com o agrupamento, você pode encontrar padrões repetidos, capturar grupos e procurar alternativas.
Busca Alternativa com Agrupamento
Vejamos um exemplo de busca alternativa:
$ grep "\(tech\|technology\)" tech.txt
Para buscar várias opções em uma string, você pode usar o símbolo de pipe |
, conforme demonstrado abaixo:
$ echo “tech technological technologies technical” | grep "\(tech\|technology\)"
#output
“tech technological technologies technical”
Grupos de Captura, Grupos de Não Captura e Padrões Repetidos
E quanto aos grupos de captura e não captura?
Para capturar grupos, é preciso criar um grupo no regex e direcioná-lo para uma string ou um arquivo:
$ echo 'tech655 tech655nical technologies655 tech655-oriented 655' | grep "\(tech\)\(655\)"
#output
tech655 tech655nical technologies655 tech655-oriented 655
Para grupos sem captura, use ?:
dentro dos parênteses.
Por fim, vamos analisar padrões repetidos. Para isso, você precisa ajustar o regex:
$ echo ‘teach tech ttrial tttechno attest’ | grep '\(t\+\)'
#output
‘teach tech ttrial tttechno attest’
Este comando procura por uma ou mais ocorrências do caractere 't'
.
#4. Classes de Caracteres
Classes de caracteres facilitam a escrita de expressões regex. Estas classes utilizam colchetes. Algumas classes comuns incluem:
[:digit:]
– Dígitos de 0 a 9.[:alpha:]
– Caracteres alfabéticos.[:alnum:]
– Caracteres alfanuméricos.[:lower:]
– Letras minúsculas.[:upper:]
– Letras maiúsculas.[:xdigit:]
– Dígitos hexadecimais, incluindo 0-9, A-F e a-f.[:blank:]
– Caracteres em branco, como tabulação ou espaço.
E várias outras!
Vejamos alguns exemplos práticos:
$ grep [[:digit]] tech.txt
$ grep [[:alpha:]] tech.txt
$ grep [[:xdigit:]] tech.txt
#5. Quantificadores
Quantificadores são metacaracteres cruciais em regex. Eles permitem especificar a quantidade exata de ocorrências de um padrão. Veja alguns exemplos:
*
→ Zero ou mais correspondências.+
→ Uma ou mais correspondências.?
→ Zero ou uma correspondência.{x}
→ Exatamente x correspondências.{x,}
→ x ou mais correspondências.{x,z}
→ De x a z correspondências.{,z}
→ Até z correspondências.
$ echo ‘teach tech ttrial tttechno attest’ | grep -E 't+'
#output
‘teach tech ttrial tttechno attest’
Neste exemplo, o comando procura por uma ou mais ocorrências do caractere 't'
. O argumento -E
indica o uso de regex estendido, que será discutido mais adiante.
#6. Regex Estendido
Para evitar o uso excessivo de caracteres de escape, você pode usar regex estendido. Ele elimina a necessidade de “escapar” certos metacaracteres. Para isso, use o argumento -E
.
$ grep -E 'in+ovation' tech.txt
#7. Usando PCRE para Pesquisas Complexas
PCRE (Perl Compatible Regular Expression) permite fazer muito mais do que escrever expressões básicas. Por exemplo, \d
corresponde a [0-9]
.
Um exemplo de uso do PCRE é a pesquisa por endereços de email:
echo "Contact me at [email protected]" | grep -P "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b"
#output
Contact me at [email protected]
O PCRE garante que o padrão corresponda a um endereço de email válido. Da mesma forma, você pode usar o PCRE para verificar padrões de data:
$ echo "The Sparkain site launched on 2023-07-29" | grep -P "\b\d{4}-\d{2}-\d{2}\b"
#output
The Sparkain site launched on 2023-07-29
Este comando encontra datas no formato AAAA-MM-DD. Você pode modificar o padrão para corresponder a outros formatos.
#8. Alternância
Para encontrar correspondências alternativas, use o símbolo de pipe “escapado” \|
.
$ grep -L ‘warning\|error’ /var/log/*.log
#output
/var/log/alternatives.log
/var/log/bootstrap.log
/var/log/dpkg.log
/var/log/fontconfig.log
/var/log/ubuntu-advantage.log
/var/log/upgrade-policy-changed.log
O resultado lista os nomes dos arquivos que contêm as palavras “warning” ou “error”.
Considerações Finais
Chegamos ao final deste guia sobre grep
e regex. O grep
com regex é extremamente útil para refinar suas buscas. Com o uso correto, você economiza tempo e automatiza tarefas, especialmente ao criar scripts ou realizar buscas em texto.
Para expandir seus conhecimentos, veja nossa lista de perguntas e respostas frequentes sobre entrevistas para cargos Linux.