Tutorial de Linux / Buscar e processar texto com grep, sort, uniq, cut e wc

Use grep para selecionar linhas que correspondam a um padrão, sort para ordená-las, uniq para agrupar repetições adjacentes, cut para extrair campos e wc para contar linhas, palavras ou bytes. Nas formas usadas nesta aula, esses comandos enviam o resultado para a saída padrão e preservam o arquivo de entrada. Ao conectá-los na ordem certa, você pode fazer pequenas tarefas de processamento de texto e conferir os resultados.

A conexão entre etapas por um pipe é explicada na aula de variáveis e fluxo de execução no shell, em inglês. Aqui, compare uma entrada conhecida com os resultados de busca e contagem.

Criar os dados de exemplo

Esta prática usa Bash e ferramentas GNU em um diretório no qual o usuário comum possa gravar. Se ~/linux-course-12-practice já existir, escolha outro nome e substitua-o nas duas primeiras linhas. Execute uma linha por vez e pare se mkdir ou cd falhar: a redireção > usada depois pode truncar um arquivo existente.

mkdir ~/linux-course-12-practice
cd ~/linux-course-12-practice
pwd

Confirme que pwd mostra o diretório novo e que records.txt ainda não existe. O sucesso de pwd sozinho não garante que cd funcionou. O comando abaixo cria cinco registros, cada um com um nome e um estado separados por dois-pontos. Os valores ready, waiting e done são dados literais do exercício e devem ser mantidos como estão para reproduzir as saídas.

printf 'alpha:ready\nbeta:waiting\nalpha:done\ngamma:ready\nbeta:ready\n' > records.txt
cat records.txt

printf transforma cada \n em uma quebra de linha; cat mostra os mesmos cinco registros na ordem informada. Todos os exemplos seguintes usam esse arquivo. Se a saída inicial for diferente, corrija a preparação antes de comparar os resultados.

Selecionar linhas com grep

grep imprime as linhas que correspondem ao padrão. A opção -n acrescenta o número da linha no arquivo de entrada:

grep -n 'ready' records.txt

Três linhas correspondem; waiting não contém ready:

1:alpha:ready
4:gamma:ready
5:beta:ready

Essa é uma busca pela ocorrência do padrão na linha, não uma validação de que o segundo campo tem um valor exato. Um estado como notready também contém ready. Para exigir o estado ready no final de uma linha desse formato, você pode usar grep -n ':ready$' records.txt.

Por padrão, grep interpreta uma expressão regular, um padrão em que caracteres como . podem ter significado especial. Para procurar uma sequência literal, use grep -F. As aspas protegem o padrão da interpretação do shell, mas não desativam a expressão regular dentro de grep.

Na execução normal do GNU grep, o estado de saída é 0 quando alguma linha é selecionada, 1 quando nenhuma corresponde e 2 quando ocorre um erro, como um arquivo inexistente. Não trate toda saída vazia como o mesmo problema: confira a mensagem de erro e o estado retornado. O guia do comando grep apresenta outras opções e condições.

Extrair campos com cut e contar com wc

cut -d: -f1 usa dois-pontos como delimitador e seleciona o primeiro campo de cada linha. Neste arquivo, o resultado contém apenas os nomes:

cut -d: -f1 records.txt
alpha
beta
alpha
gamma
beta

cut trabalha com delimitadores simples. Ele não interpreta campos entre aspas nem quebras de linha dentro de campos como um analisador de CSV completo. Por padrão, uma linha sem o delimitador também é impressa, a menos que você use -s. Confira o formato dos dados antes de reutilizar a extração em outro arquivo.

Com wc -l, o resultado indica 5 ao lado de records.txt:

wc -l records.txt

wc -l conta caracteres de nova linha. Neste exercício, todos os registros terminam com \n, por isso a contagem corresponde aos cinco registros. Um último trecho sem nova linha final não acrescenta uma unidade a essa contagem, mesmo que apareça como uma linha no editor.

wc -w conta palavras separadas por espaços em branco, não os campos separados por dois-pontos: os cinco registros deste arquivo contam como cinco palavras. wc -c conta bytes e wc -m conta caracteres conforme a codificação reconhecida pela localidade. Em UTF-8, letras acentuadas podem ocupar mais de um byte; portanto, bytes e caracteres não são necessariamente a mesma quantidade.

Conectar sort e uniq na ordem certa

sort ordena as linhas. uniq agrupa somente linhas iguais adjacentes, por isso ordenar antes de agrupar permite reunir nomes repetidos que estavam separados na entrada. O pipe | conecta a saída padrão de um comando à entrada padrão do seguinte:

cut -d: -f1 records.txt | sort | uniq -c

Leia a sequência da esquerda para a direita: cut extrai os nomes, sort aproxima os nomes iguais e uniq -c conta cada grupo. O resultado esperado é:

      2 alpha
      2 beta
      1 gamma

As contagens são alpha 2, beta 2 e gamma 1. Os espaços antes dos números e a ordem de comparação podem variar com a implementação e a localidade. Neste conjunto, aplicar uniq -c diretamente aos nomes, sem a ordenação, mantém cinco grupos de uma ocorrência, pois nomes iguais não são consecutivos.

A unidade escolhida também importa. Se você ordenar e agrupar os registros inteiros, alpha:ready e alpha:done continuam sendo linhas diferentes. Extraia primeiro o campo que define uma repetição para a sua pergunta. A ordenação pode depender de LC_COLLATE e de outras configurações de localidade; compare essas condições quando os resultados diferirem entre sistemas, especialmente com maiúsculas e acentos.

Escolher a ferramenta e conferir cada etapa

Objetivo Ferramenta Condição principal
Selecionar linhas correspondentes grep Distinguir expressão regular de padrão literal
Ordenar linhas sort Conferir localidade e critério de ordenação
Agrupar repetições ou contar frequências uniq Os valores iguais precisam ser adjacentes
Extrair campos delimitados simples cut Definir delimitador e número do campo
Contar linhas, palavras ou bytes wc Escolher a opção conforme o que será contado

Se a saída estiver vazia ou diferente do esperado, examine primeiro cat records.txt. Depois execute as etapas separadamente para descobrir se a diferença surgiu no padrão, no delimitador, na ordenação ou na contagem. No Bash, por padrão, o estado de uma pipeline é o do último comando: uma etapa anterior pode falhar enquanto a última termina com sucesso. Leia também os erros das etapas anteriores; em scripts, avalie set -o pipefail conforme a política de tratamento de erros.

Compare agora a mudança de um único dado. Parta do arquivo original de cinco registros, acrescente uma linha beta:ready e conte novamente. A frequência de beta passa de 2 para 3, e o total de novas linhas passa de 5 para 6. Em seguida, o mesmo bloco restaura os dados iniciais e repete a contagem.

printf 'beta:ready\n' >> records.txt
cut -d: -f1 records.txt | sort | uniq -c
wc -l records.txt
printf 'alpha:ready\nbeta:waiting\nalpha:done\ngamma:ready\nbeta:ready\n' > records.txt
cut -d: -f1 records.txt | sort | uniq -c
wc -l records.txt

>> acrescenta ao final; > substitui o conteúdo. A restauração deve ser aplicada somente ao records.txt criado nesta prática, sem alterações próprias que você queira guardar. Ao final, confira alpha 2, beta 2, gamma 1 e cinco linhas novamente. O formato mostrado por cat records.txt deve voltar ao original.

Documentação oficial

O manual do GNU grep descreve os padrões e estados de saída. O manual do GNU Coreutils reúne as opções de sort, uniq, cut e wc. Para a conexão e o estado das etapas, consulte a documentação de pipelines do Bash.