Tela Preta episódio 9: Contar palavras com egrep|sort|uniq

★ Lista de episódios da série Tela Preta: 1 2 3 4 5 6 7 8 9

Para comemorar a marca de 1.000 assinantes no meu canal do YouTube 🎉, fiz mais um episódio da série Tela Preta 🎉

Tela Preta é a minha série de vídeos nerds gravados na linha de comando do Unix, demonstrando o “jeito shell script” de resolver problemas. Todos os vídeos contam com narração e legendas em português, estão em alta resolução (HD) e são reais: sem ensaio, sem cortes, sem edição posterior. Assine meu canal lá no YouTube para ser notificado(a) quando sair um vídeo novo.

Desta vez a tarefa é bem legal: contar quantas vezes cada palavra aparece em um texto, e no final, mostrar as 10 palavras mais frequentes. Assim:

$ cat hino-nacional.txt | comando-mágico
   7 Pátria
   7 Brasil
   6 amada
   5 teu
   4 mais
   4 Terra
   4 Salve
   3 que
   3 própria
   3 forte
$

Parece complicado, não? Mas você vai ver que a solução é simples e usa poucos comandos em uma única linha. E viva o Unix e suas ferramentas poderosas! 💪

Curta o vídeo:

A manha é usar o uniq -c que conta quantas vezes cada linha consecutiva aparece em um texto. Então o que eu preciso fazer, é modificar o meu texto original para que ele fique nesse formato de linhas consecutivas, ou seja:

  • Cada palavra deve aparecer sozinha na linha (uma palavra por linha)
  • Palavras iguais devem estar agrupadas (uma após a outra)

Há várias maneiras de deixar uma palavra por linha: xargs -n 1, sed, awk, loop... Mas nesse vídeo fiz de um jeito diferente. Aproveitei a opção -o do egrep, que em vez de mostrar a linha toda no resultado, mostra somente o texto casado, um por linha em caso de múltiplos matches na mesma linha. Bingo! Aí foi só fazer uma expressão regular para casar todas as palavras do texto: \w+. O bom é que isso também pega as nossas palavras acentuadas do português.

Para agrupar as palavras iguais, basta um sort. Com o detalhe que usei a opção -f para que ele ignore a diferença entre letras maiúsculas e minúsculas. Isso faz com que “Pátria” e “pátria” sejam agrupadas, assim serão identificadas como a mesma palavra no uniq -c. Ah sim, também precisei passar a opção -i no uniq, para que ele também trate as maiúsculas e minúsculas da mesma forma.

Ali no meio, fiz um filtro para eliminar as palavras de uma e duas letras. Eu só queria contar palavras de três ou mais letras. Usei um grep ..., que exige que a linha tenha pelo menos três caracteres quaisquer, descartando as demais linhas. Lembra que o ponto é um metacaractere também? Viva as regexes!

No final do comando, basta formatar o resultado, ordenando numericamente e mostrando somente as 10 primeiras linhas. Essa parte é facinha, né? Um sort, um head e pronto.

Resumo dos comandos:

  • grep, egrep — pesquisa linhas em um texto
  • sort — ordena linhas
  • uniq — remove/extrai/conta linhas repetidas
  • head — mostra somente as primeiras N linhas

Saiba mais sobre os tópicos do vídeo:

Histórico da linha de comando:

wc -w /etc/passwd

man uniq | grep count
man uniq | grep -A 1 count
vi numeros
cat numeros | uniq -c
cat numeros | sort | uniq -c
cat numeros | sort   #| uniq -c
cat numeros | sort | uniq -c

pbpaste
pbpaste > hino.txt
cat hino.txt
echo >> hino.txt
cat hino.txt

cat hino.txt | uniq -c
cat hino.txt | sort | uniq -c
cat hino.txt | xargs -n 1
cat hino.txt | xargs -n 5
cat hino.txt | xargs -n 2
cat hino.txt | xargs -n 1

echo um, dois, tres.
echo um, dois, tres. | egrep -o '\w+'

cat hino.txt | egrep -o '\w+'
cat hino.txt | egrep -o '\w+' | sort | uniq -c
cat hino.txt | egrep -o '\w+' | sort | uniq -c | sort -n
cat hino.txt | egrep -o '\w+' | sort | uniq -c | sort -n -r
cat hino.txt | egrep -o '\w+' | sort | uniq -c | sort -n -r | head
cat hino.txt | egrep -o '\w+' | sort | uniq -c | sort -n -r | head -n 15

cat hino.txt | egrep -o '\w+' | grep ..........   #| sort | uniq -c | sort -n -r | head -n 15
cat hino.txt | egrep -o '\w+' | grep .......   #| sort | uniq -c | sort -n -r | head -n 15
cat hino.txt | egrep -o '\w+' | grep ... | sort | uniq -c | sort -n -r | head -n 15

cat hino.txt | egrep -o '\w+' | grep ... | sort | uniq -c | sort -n -r | grep tria
sort --help | grep case
man uniq | grep -- -i
cat hino.txt | egrep -o '\w+' | grep ... | sort -f | uniq -c -i | sort -n -r | grep tria
cat hino.txt | egrep -o '\w+' | grep ... | sort -f | uniq -c -i | sort -n -r | head

conta_palavras(){ egrep -o '\w+' | grep ... | sort -f | uniq -c -i | sort -n -r | head; }

cat hino.txt | conta_palavras
cat /etc/passwd | conta_palavras

Ah, usuários das Funções ZZ não precisam lembrar de todos esses comandos e podem usar diretamente a zzcontapalavras ;)

cat hino.txt | zzcontapalavras -i -n 10
— EOF —

Gostou desse texto? Aqui tem mais.