Pesquisa de site

Como usar o comando grep do Linux


Aprenda o básico sobre como pesquisar informações em seus arquivos e, em seguida, baixe nossa folha de dicas para obter um guia de referência rápida sobre grep e regex.

Um dos comandos clássicos do Unix, desenvolvido em 1974 por Ken Thompson, é o comando Global Regular Expression Print (grep). É tão onipresente na computação que é frequentemente usado como um verbo (“explorar um arquivo”) e, dependendo de quão geek é o seu público, ele também se encaixa perfeitamente em cenários do mundo real. (Por exemplo, "Terei que usar o grep em meus bancos de memória para recuperar essas informações".) Resumindo, grep é uma forma de pesquisar em um arquivo um padrão específico de caracteres. Se isso soa como a moderna função Find disponível em qualquer processador de texto ou editor de texto, então você já experimentou os efeitos do grep na indústria da computação.

Longe de ser apenas um comando antigo e curioso que foi suplantado pela tecnologia moderna, o verdadeiro poder do grep reside em dois aspectos:

  • Grep funciona no terminal e opera em fluxos de dados, para que você possa incorporá-lo em processos complexos. Você não pode apenas encontrar uma palavra em um arquivo de texto; você pode extrair a palavra, enviá-la para outro comando e assim por diante.
  • Grep usa expressões regulares para fornecer um recurso de pesquisa flexível.

Aprender o comando grep é fácil, embora exija alguma prática. Este artigo apresenta alguns de seus recursos que considero mais úteis.

[Baixe nossa folha de referência gratuita do grep]

Instalando o grep

Se estiver usando Linux, você já tem o grep instalado.

No macOS, você tem a versão BSD do grep. Isso difere um pouco da versão GNU, então se você quiser acompanhar exatamente este artigo, instale o GNU grep a partir de um projeto como Homebrew ou MacPorts.

Grep básico

A sintaxe básica do grep é sempre a mesma. Você fornece ao comando grep um padrão e um arquivo que deseja pesquisar. Em troca, ele imprime cada linha no seu terminal com uma correspondência.

$ grep gnu gpl-3.0.txt
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
<http://www.gnu.org/licenses/>.
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

Por padrão, o comando grep diferencia maiúsculas de minúsculas, então "gnu" é diferente de "GNU" ou "Gnu". Você pode ignorar a capitalização com a opção --ignore-case.

$ grep --ignore-case gnu gpl-3.0.txt
                    GNU GENERAL PUBLIC LICENSE
  The GNU General Public License is a free, copyleft license for
the GNU General Public License is intended to guarantee your freedom to
GNU General Public License for most of our software; it applies also to
[...16 more results...]
<http://www.gnu.org/licenses/>.
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

Você também pode fazer com que o comando grep retorne todas as linhas sem uma correspondência usando a opção --invert-match:

$ grep --invert-match \
--ignore-case gnu gpl-3.0.txt
                      Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
[...648 lines...]
Public License instead of this License.  But first, please read

Tubos

É útil poder localizar texto em um arquivo, mas o verdadeiro poder do POSIX é sua capacidade de encadear comandos por meio de "pipes". Acho que meu melhor uso do grep é quando ele é combinado com outras ferramentas, como cut, tr ou curl.

Por exemplo, suponha que eu tenha um arquivo que lista alguns documentos técnicos que desejo baixar. Eu poderia abrir o arquivo e clicar manualmente em cada link e, em seguida, clicar nas opções do Firefox para salvar cada arquivo em meu disco rígido, mas isso leva muito tempo e cliques. Em vez disso, eu poderia procurar os links no arquivo, imprimindo apenas a string correspondente usando a opção --only-matching:

$ grep --only-matching http\:\/\/.*pdf example.html
http://example.com/linux_whitepaper.pdf
http://example.com/bsd_whitepaper.pdf
http://example.com/important_security_topic.pdf

A saída é uma lista de URLs, cada uma em uma linha. Este é um ajuste natural para como o Bash processa dados, então, em vez de imprimir as URLs em meu terminal, posso simplesmente canalizá-las para curl:

$ grep --only-matching http\:\/\/.*pdf \
example.html | curl --remote-name

Isso baixa cada arquivo, salvando-o de acordo com seu nome de arquivo remoto em meu disco rígido.

Meu padrão de pesquisa neste exemplo pode parecer enigmático. Isso ocorre porque ele usa expressões regulares, um tipo de linguagem “curinga” que é particularmente útil ao pesquisar amplamente em muito texto.

Expressão regular

Ninguém tem a ilusão de que a expressão regular ("regex", abreviadamente) seja fácil. No entanto, acho que muitas vezes tem uma reputação pior do que merece. É certo que existe a possibilidade de as pessoas se tornarem um pouco espertas demais com a regex até que ela se torne tão ilegível e tão ampla que se dobre sobre si mesma, mas você não precisa exagerar na sua regex. Aqui está uma breve introdução ao regex da maneira como eu o uso.

Primeiro, crie um arquivo chamado example.txt e insira este texto nele:

Albania
Algeria
Canada
0
1
3
11

O elemento mais básico do regex é o humilde caractere .. Representa um único caractere.

$ grep Can.da example.txt
Canada

O padrão Can.da retornou Canada com sucesso porque o caractere . representava qualquer um caractere.

O curinga . pode ser modificado para representar mais de um caractere com estas notações:

  • ? corresponde ao item anterior zero ou uma vez
  • * corresponde ao item anterior zero ou mais vezes
  • + corresponde ao item anterior uma ou mais vezes
  • {4} corresponde ao item anterior quatro vezes (ou qualquer número inserido entre colchetes)

Armado com esse conhecimento, você pode praticar regex em example.txt a tarde toda, vendo quais combinações interessantes você consegue. Alguns não funcionarão; outros o farão. O importante é analisar os resultados para entender o porquê.

Regex avançado requer a opção --extended-regexp ou -E.

Por exemplo, isso não retorna nenhum país:

$ grep -E A.a example.txt

Ele falha porque o caractere . só pode corresponder a um único caractere, a menos que você o suba de nível. Usando o caractere *, você pode dizer ao grep para corresponder a um único caractere zero ou quantas vezes forem necessárias até chegar ao final da palavra. Como você conhece a lista com a qual está lidando, sabe que zero vezes é inútil neste caso. Definitivamente não há nomes de países com três letras nesta lista. Então, em vez disso, você pode usar + para corresponder um único caractere pelo menos uma vez e novamente quantas vezes forem necessárias até o final da palavra:

$ grep -E A.+a example.txt
Albania
Algeria

Você pode usar colchetes para fornecer uma lista de letras:

$ grep -E [AC].+a example.txt
Albania
Algeria
Canada

Isso também funciona para números. Os resultados podem te surpreender:

$ grep [1-9] example.txt
1
3
11

Você fica surpreso ao ver 11 em uma pesquisa pelos dígitos de 1 a 9?

O que acontece se você adicionar 13 à sua lista?

Esses números são retornados porque incluem 1, que está na lista de dígitos correspondentes.

Como você pode ver, regex é uma espécie de quebra-cabeça, mas por meio de experimentação e prática, você pode se sentir confortável com ele e usá-lo para melhorar a maneira como você analisa seus dados.

Baixe a folha de dicas

O comando grep tem muito mais opções do que demonstrei neste artigo. Existem opções para melhor formatar resultados, listar arquivos e números de linha contendo correspondências, fornecer contexto para resultados imprimindo as linhas ao redor de uma correspondência e muito mais. Se você está aprendendo grep, ou apenas o usa com frequência e recorre a pesquisas em suas páginas de informações, você fará um favor a si mesmo baixando nossa folha de dicas para ele. A folha de dicas usa opções curtas (-v em vez de --invert-matching, por exemplo) como uma forma de familiarizá-lo com a abreviação grep comum. Ele também contém uma seção regex para ajudá-lo a lembrar os códigos regex mais comuns. Baixe a folha de dicas do grep hoje! 

Artigos relacionados: