Mostrando postagens com marcador tr. Mostrar todas as postagens
Mostrando postagens com marcador tr. Mostrar todas as postagens

quarta-feira, 21 de dezembro de 2011

Soma dos débitos do extrato do Banco do Brasil

  Eu sempre fiz o controle dos meus gastos e para ter a resposta do custo do mês, desenvolvi um script que soma todas as parcelas debitadas da minha conta corrente do banco do Brasil.
  Começou de uma forma bem simples. Um conjunto de entradas e saídas era sequênciado da seguinte forma:
  • o comando cat exibe todo o conteúdo
  • o comando cut mostrar do caracter 60 em diante
  • o grep exibe somente as linhas de débito (indicadas por um "D")
  • o awk exibe somente o primeiro campo da linha de débito
  • o comando sed substitui vírgula por ponto
  • o paste e suas opções transformam a listagem de coluna para linha e insere um sinal de mais (+) entre os números
  • o comando bc faz a soma
Observação: a necessidade de substituir a vírgula por ponto é devido ao bc requerer este símbolo para interpretar valores fracionários.

  Até Maio de 2007 e anterior a esta data, o comando era:

cat extrato_07_05.txt | cut -c 60- | grep D | awk '{printf("%s\n",$1)}' | sed 's/,/./g' | paste -s -d"+" | bc

  De Junho de 2007 até o presente, usa-se:

cat extrato_07_06.txt | cut -c 71- | grep D | awk '{printf("%s\n",$1)}' | sed 's/,/./g' | paste -s -d"+" | bc

  Estes comandos combinados funcionavam para valores até 999 reais. A partir dos valores contendo 4 dígitos, este é exibido com um ponto separador de milhar. Exemplo: 1.000,00   Como consequência, causa um erro no interpretador do bc. Para resolver o problema, apresento a solução abaixo bem como os comentários.

#!/bin/bash
# Variáveis mes e ano capturam a data
mes=`date +%m`
ano=`date +%Y`

# Exige o número do arquivo ao executar o comando
 if [ $# != 1 ]
   then
    echo "Argumento: nome_de_arquivo"
    exit 1
  fi

cat $1 | cut -c 71- | grep D | awk '{printf("%s\n",$1)}' | sed 's/,/./g' > extrato.txt
# Conta a quantidade de linhas ao ler o arquivo
total_linhas=`wc -l extrato.txt | cut -f1 -d" "`
# Apaga o arquivo
rm -f gasto_"$ano"_$mes.txt
# Loop para executar um conjunto de ações até o final do arquivo
for i in `seq $total_linhas`
  do
# Analisa cada linha e conta o número de pontos (separadores de milhar e da parte fracionária)
   um_ponto=`head -n $i extrato.txt | tail -n 1 | tr -cd "." | wc -c`
   if [ $um_ponto = 1 ]
    then
# Se for apenas 1 ponto, simplesmente exibe o valor
    head -n $i extrato.txt | tail -n 1
   fi

# Analisa cada linha e conta o número de pontos (separadores de milhar e da parte fracionária)
  dois_pontos=`head -n $i extrato.txt | tail -n 1 | tr -cd "." | wc -c`
   if [ $dois_pontos = 2 ]
    then
# Se forem 2 pontos, substitui o primeiro ponto por nada (ponto aparece somente para parte fracionária)
    echo `head -n $i extrato.txt | tail -n 1` | sed 's/\.//'
   fi
  done >> gasto_"$ano"_$mes.txt
paste -s -d"+" gasto_"$ano"_$mes.txt | bc

sexta-feira, 5 de agosto de 2011

Renomeando arquivos para o padrão Unix


Muitas vezes recebo arquivos que vem com espaços e parenteses e não é muito conveniente tratá-los no shell. Então eu prefiro eliminar esses caracteres. É o serviço do script abaixo.
Para executar, proceda assim:

./script nome_arquivo

para que o script saiba qual arquivo deve renomear.

Então, a primeira providência é uma checagem se foi passado o argumento através da condição if [ $# != 1 ].
Estando tudo bem, o script começa a renomear. O nome do arquivo fica armazenado na variável $1 e passa a transferir novos valores para as variáveis seguinte que foram usados nomes bem intuitivos.
De com_espaco passa o novo valor para sem_espaco.
sem_espaco para minuscula através do comando tr.
De minuscula para dash que substitui a sequência "_-_" por "-" através do sed.
Do dash para abre_parenteses e em seguida para fecha_parenteses que em ambos os casos usam o sed para substituir os caracteres.




#!/bin/bash
# remove spaces, uppercase to lowercase, replace " - " for "-", replace "(" for "-" and replace ")"for ""

# If file name isn't given show message
if [ $# != 1 ]
  then
   echo "Argumento: nome_de_arquivo"
   exit 1
fi

# grab the file name
com_espaco=`ls -1 "$1"`
# change space for underline
sem_espaco=`ls -1 "$1" | sed 's/ /_/g'`
#echo "$sem_espaco"
mv -v "$com_espaco" "$sem_espaco"
minuscula=$(echo "$sem_espaco" | tr A-Z a-z)
# change upper for lowercase
mv -v "$sem_espaco" "$minuscula"
# change _-_ for -
dash=`echo "$minuscula" | sed 's/_-_/-/'`
mv -v "$minuscula" "$dash"

ls "$dash" | grep "("
if [ $? -eq 0 ]
  then
   abre_parenteses=`ls "$dash" | sed 's/(/-/g'`
   mv -v "$dash" "$abre_parenteses"
fi

ls "$abre_parenteses" | grep ")"
if [ $? -eq 0 ]
  then
   fecha_parenteses=`ls "$abre_parenteses" | sed 's/)//g'`
   mv -v "$abre_parenteses" "$fecha_parenteses"
fi


Podemos automatizar este trabalho se forem muitos arquivos. Se for para os arquivos do mesmo diretório, há uma forma bem simples. Digite a linha de comando no seu terminal:


$ ls -1 | { while read arq; do ./script "$arq"; done; }


Apacerá uma mensagem de erro caso o nome de arquivo não tenha parênteses, mas garanto que no fim tudo estará devidamente renomeado.
É mais ágil quando é dado um duplo clique numa palavra e o terminal seleciona inteira facilitando o trabalho de copiar e colar.