De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.
Colaboração: Julio Cezar Neves
Data de Publicação: 11 de julho de 2019
Relacionamos a seguir um contador de palavras completo e documentado.
Pode ter 3 tipos de saída:
Pode receber os dados como parâmetro:
$ ContaPalavras.sh arq*
Ou via pipe:
$ echo arq* | ContaPalavras.sh $ ls arq* | ContaPalavras.sh
Em caso de erro, a mensagem respectiva será mandada para a saída de erros, então se você fizer:
$ ContaPalavras.sh ArqQueNaoExiste 2> /dev/null
ou:
$ ContaPalavras.sh ArqQueNaoExiste 2>&-
Não haverá saída de erro, mas o código de retorno ($?) será 1.
#!/bin/bash
declare -A TodasPalavras
declare -i Minimo=4
trap "rm /tmp/Arquivao 2>&-; exit" 0 2 3 15
function Uso # Dá msg de erro, ensina como usar e aborta
{
echo "
$0: Faltou nome(s) válido(s) de arquivo(s)
Os nome(s) do(s) arquivo(s) pode(m) ser passado(s) das seguintes maneiras:
echo ARQUIVO | $0
$0 ARQUIVO
Metacaracteres podem ser usados. P. ex: $0 ARQ*" >&2 # A msg de erro é enviada para std err (>&2)
exit 1
}
### De onde está vindo o dado, pipe ou parâmetro?
if [[ -t 0 ]] # Testa se o dado não está em stdin. Zero é o identificador da entrada primária (|, < ou <<<)
then
(($#)) || { # Testa se tem parâmetro
echo Passe os dados via pipe, arquivo ou passagem de parâmetros >&2
exit 1
}
Parms="$@" # Coloca em Parms os parâmetros passados
else
Parms=$(cat -) # Coloca em $Parms o conteúdo de stdin
fi
set $Parms # O conteúdo de $Parms se torna os parâmetros do prg
ls $Parms &>- || Uso # Não passou parâmetro ou arq. não existe. Obs: &>- fecha as saídas primaria e de erro
Parms=$(file $Parms | grep text | cut -f1 -d:) # retira da lista arquivos que não são de texto puro
### Início da rotina que conta palavras ###
cat $Parms > /tmp/Arquivao # Junta o texto de todos os arquivos num só arquivão
# A linha a seguir pega cada palavra do arquivo passado após, apagar pontuação e números e pôr tudo em caixa baixa
for Palavra in $(tr [:punct:][:digit:] ' ' < /tmp/Arquivao | tr A-Z a-z)
do
((${#Palavra} < Minimo)) && continue # Despreza palavras menores que o minimo definido
let TodasPalavras[$Palavra]++
done
### Pulo do gato! Concatena o vetor que contém as contagens com seus índices (palavras),
### ordena numéricamente e divide em colunas para facilitar consulta
paste <(tr ' ' '\n' <<< ${TodasPalavras[@]}) <(tr ' ' '\n' <<< ${!TodasPalavras[@]}) | # Concatena as qtdes com as palavras
sort -nr | # Classifica numéricamente em ordem reversa (maiores primeiro)
column -c80 -x
### Fim da rotina que conta palavras ###
### Se quiser uma saída gráfica, comente as 3 linhas acima e descomente as 3 linhas a seguir:
# paste <(tr ' ' '\n' <<< ${TodasPalavras[@]}) <(tr ' ' '\n' <<< ${!TodasPalavras[@]}) |
#+ sort -nr |
#+ zenity --list --column Col1 --column Col2 --column Col3 --hide-header --height 700 --width 400
### A saída das linhas a seguir também é gráfica, porém preciso do yad - recomendo muito instalar pq é bom demais
# paste <(tr ' ' '\n' <<< ${TodasPalavras[@]}) <(tr ' ' '\n' <<< ${!TodasPalavras[@]}) |
#+ sort -nr |
#+ column -c80 -x |
#+ yad --text-info --fontname "monospace 10" --height 700 --width 600