AprendiNoLinux
(usa Ubuntu)
Enviado em 22/09/2011 - 23:32h
Iniciei meu aprendizado mesmo em Shell Script tem na verdade uns 90 dias. Antes era tudo na orelhada mesmo.
Meus primeiros contatos aqui no fórum de cara se mostraram que o caminho estava errado e fui muito bem orientado.
Segue algumas construções que fiz e estou batendo cabeça para fazer rsrs.
Roadmap do CaxIta - Acessos em Shell Script ( inclui Kit.Acessos.lib ) -
http://va.mu/F7ax
Praticamente estou refazendo todos os códigos novamente porque a linha de trabalho não estava boa. Após toques do Prof. Raimundo, Ronim, Udson, Alexandre, fui revendo a realidade que não é a dos livros.
Funciona 100% o código que está colorizado.
A versão 2.0 que será baseada na 1.0 será em modo gráfico. Tem um outro colaborador do VOL que está me dando uns toques.
O que não estou mudando é a forma de documentar, analisar, preparar a construção dos Scripts.
Procurei documentar a minha forma de pensar aqui:
http://www.vivaolinux.com.br/topico/Shell-Script/Sugestoes-para-convencoes-na-programacao-de-SHELL-S...
Com a colaboração de poucos participantes, algumas dúvidas foram sanadas e a vivência está me fazendo remodelar e evoluir.
De qualquer modo, pretendo no futuro criar alguns artigos sobre a minha experiência no desenvolvimento de Shell Script e suas convenções.
Sinto que estou começando a dominar o trem rsrs.
Muito por fazer e aprender...
A lição eu já sei. Pesquise, pesquise, pergunte, pergunte, compartilhe, compartilhe, ajude, ajude.
#!/bin/bash
# file: cardapio.sh
# author: Geraldo T. Albuquerque aka @GA_Tux ou @AprendinoLinux
# co-author: Hudson Moreira Guimaraes dos Santos aka @hudyfx
# version: 1.0 beta
# objetives: Script coleta a digitação de códigos de uma lanchonete.
# detalhes: Lembrei do Roberto Carlos rss. São tantas emoções....
# ----------------------------------------------------------------------------
# Desenvolva um programa em shell que leia o código do item pedido,
# a quantidade e calcule o valor a ser pago por aquele lanche.
# Considere que a cada execução somente será calculado um item.
# ----------------------------------------------------------------------------
# Roadmap e changelog:
# 1 - Criar uma lista com os produtos e seus preços. (ok)
# 2 - Carregar a lista de preço via arquivo (ok) grato ao @hudyfx
# 3 - Permitir escolher o produto na lista. (ok) grato ao @hudyfx
# 4 - Mostrar o sub-total que está dando a conta. (ok)
# 5 - Mostrar os itens escolhidos no pedido. (ok)
# 6 - Finalizar a comanda. (ok)
# 7 - Salvar o pedido temporário ok (está em memória)
# 8 - Salvar o pedido finalizado ? #FIXME Falta aprender aproveitar a tela.
# 9 - Montar ticket do pedido. (ok) Créditos ao @hudyfx
# 10- Configuração para usar vários arquivos de cardápio. (ok)
# ----------------------------------------------------------------------------
# XXX: Formatar a saída está uma dificuldade, alinhar a direita.
# XXX: Duas POGs foram criadas para quebrar o galho, mas não está legal.
# TODO: Falta criar um cabeçalho com os nomes de campos no arquivo cardapio.txt
# ----------------------------------------------------------------------------
# Variáveis globais
# ----------------------------------------------------------------------------
start=0 # Controla o início das digitações.
valor_pedido=0 # Acumula o valor do pedido em aberto.
tab_precos= # Armazenar a tabela completa com preços , códigos e nomes.
_itens_pedido= # Coleta os itens digitados no pedido.
cont_iped="0" # Contador de itens no pedido.
# ----------------------------------------------------------------------------
# Configs para o arquivo de cardápio.
# ----------------------------------------------------------------------------
_CONF_CARDAPIO="cardapio.txt"
_DIR_CARDAPIO="${PWD}"
_FILE_CARDAPIO="${_DIR_CARDAPIO}/${_CONF_CARDAPIO}"
# ----------------------------------------------------------------------------
# Reconfigura as variáveis globais após fechar e finalizar o pedido.
function inicializa()
{
valor_pedido="0"
cont_iped="0"
_itens_pedido=
start=0
}
# Executa rotina de impressão e finalização do pedido. Cobra até imposto rsrs.
# Não cobra o imposto, mas poderia cobrar. Fica como desafio para alguém.
function finaliza()
{
if [ "$valor_pedido" -gt 0 ]
then
# Neste ponto pode ser adicionado gravação ou impressão do pedido.
ped_numero=$(date +"%s")
clear
echo "+=========================================+"
echo "|Finalizando o Pedido nº.....: ${ped_numero} |"
echo "+=========================================+"
echo "|Deseja nota fiscal paulista ? kkkkk |"
echo "+---+-------------------------------+-----+"
echo "|Cod| Produto |Preço|"
echo "+---+-------------------------------+------"
itens_do_pedido
echo "+---+-------------------------------+------"
echo " Total da fatura....................: ${valor_pedido}"
echo "+=========================================+"
echo "|Impostos a pagar: Iss, icms, pis, cofins |"
echo "+=========================================+"
read -t 10
inicializa
return
else
echo ""
echo "================================================="
echo "Você não digitou nenhum pedido ainda."
echo "Está com pressa ? rsrs "
echo "================================================="
read -t 5
fi
}
# Se o seek na tabela de memória falhar, vai alertar o usuário.
function naoexiste()
{
echo ""
echo "Produto $numero não existe, confira o cardápio !!! "
read -t 5
}
# Responsável por armazenar os itens no arquivo de memória dos pedidos.
# Note que se desejar armazenar em disco, é muito fácil nesta estrutura.
function digitei()
{
# Agora validando o código do produto com base no arquivo de tabela de preços.
# Apreoveita a tabela que já está em memória. (Desafio pessoal)
# Usar uma tabela armazenada em disco é fácil, difícil é controlar em memória.
for meuvalor in ${tab_precos[@]}
do
meu_cod=$(echo ${tab_precos[$numero]} | cut -d: -f1)
meu_nome_prod=$(echo ${tab_precos[$numero]} | cut -d: -f2)
meu_preco=$(echo ${tab_precos[$numero]} | cut -d: -f3)
if [ "$meu_cod" = "$numero" ]
then
valor_pedido=$((valor_pedido + meu_preco))
#Salvando os itens do pedido.
cont_iped=$((cont_iped +1))
# Que POG lascada, mas não conheço outra forma de fazer.
SEPA1="|"
SEPA2=" |"
if [ ${#meu_preco} -eq 4 ]
then
posit=${SEPA1}
else
posit=${SEPA2}
fi
_itens_pedido["$cont_iped"]="|${meu_cod}| ${meu_nome_prod}| ${meu_preco}${posit}"
# Salva o novo valor digitado. Não importa se é repetido ou não.
digitando["$contador"]="$1"
# Faz incremento do contador para o próximo passo.
let contador++
return
fi
done
naoexiste ; return
}
# Mostra os códigos já digitados e o valor acumulado do pedido.
function digitado()
{
if [ $start = "0" ]
then
start="1"
return
fi
echo "Produtos digitados.: ${digitando[@]} "
echo "Sub-Total é........: ${valor_pedido} "
}
# Área principal da digitação. Deste local pode-se ir a qualquer lugar.
function digitar()
{
while true
do
clear
mostramenu
digitado
echo ""
echo -n "Digite o código do produto...:"
read numero
if test $numero -gt 0
then
digitei $numero
digitado
else
_opcoes "$numero"
mostramenu
fi 2> /dev/null
done
}
# Fica como desafio para alguém que queira praticar.
# XXX: Falta dominar o processo de salvar usando as linhas de echo + tela.
function salva_pedido()
{
: # Caso precise salvar o pedido finalizado.
}
# XXX: Tenho dificulade em salvar o pedido linha a linha usando as telas.
function salva_tmp()
{
: # Caso precise salvar o pedido temporário.
}
# Prepara a chamada para listar o andamento do pedido.
function listar()
{
if [ "$valor_pedido" -gt 0 ]
then
listar_pedido
else
echo ""
echo "================================================="
echo "Você não digitou nenhum pedido ainda."
echo "Está com pressa ? rsrs "
echo "================================================="
read -t 5
fi
}
# Efetiva a listagem do pedido neste momento.
function listar_pedido()
{
clear
echo "+=========================================+"
echo "|Pedido digitado |"
echo "+=========================================+"
echo ""
echo "+---+-------------------------------+-----+"
echo "|Cod| Produto |Preço|"
echo "+---+-------------------------------+------"
itens_do_pedido
echo "+---+-------------------------------+------"
echo " Sub-total do pedido................: ${valor_pedido}"
echo "+=========================================+"
echo -n " ENTER retorna ao pedido."
read
return
}
# Contém os produtos digitados e já formatado para o padrão da saída.
# TODO: Valores quando formam gravados não estão alinhados a direita.
# TODO: Aqui a recuperação é apenas a leitura do array em memória.
function itens_do_pedido()
{
local i
i="1"
while true
do
if [ "${#_itens_pedido[$i]}" -gt 0 ]
then
echo "${_itens_pedido[$i]} "
else
# Acabou o pedido, posso sair.
return
fi
let i++
done
return
}
# Dá de pinote do sistema. Agora com mais équio.
# FIXME: Se tem pedido em aberto, não avisa o usuário.
# FIXME: Próxima versão precisa fazer esta verificação.
function sair()
{
echo ""
echo "+---------------------------------------------------------+"
echo "|Finalizando o sistema bye. Digitação não foi gravada !!! |"
echo "|É importante verificar se não existe um pedido em aberto.|"
echo "|Fica como pendência a ser resolvida |"
echo "+---------------------------------------------------------+"
read -t 0.5
exit
}
# Quase todos os erros levam a esta tela genérica.
function erro()
{
echo ""
echo "+------------------------------------------------------+"
echo "|Opção digitada é inválida |"
echo "|Precisa de ajuda ? use o help |"
echo "+------------------------------------------------------+"
read -t 2
}
# XXX: Uma tremenda POG para fazer a manobra no posicionamento.
# XXX: Não encontrei uma forma melhor para posicionar os produtos e valores.
# XXX: Se alguém quiser colaborar com algum regex ou uma nova forma, avise.
function completa_texto()
{
#------------------------------------------------------------------------------
# Recebe o Tamanho total = tt (numérico)
# Recebe a String a ser tratada = ts
# Calcula o Tamanho a completar = (tt -ts)
# Exemplo: Se um texto é "cachorro quente" ele tem 15 de tamanho preenchido.
# Se o tamanho do campo é de 30, vou completar com 15 ???.
#------------------------------------------------------------------------------
if [ "$1" = "-h" ]; then
# Solicitando Ajuda para usar a função.
clear
echo "+------------------------------------------------------+"
echo "|Ajuda para usar a função completa_texto |"
echo "+------------------------------------------------------+"
echo "|Uso: completa_texto 20 'seu texto' '.' 'D' |"
echo "+------------------------------------------------------+"
echo "|Útil quando você pega 1 campo do banco de dados. |"
echo "|Formatar a linha com um determinado tamanho desejado. |"
echo "|Se você conhece algum regex para completar, me avise. |"
echo "|Você pode completar com qualquer caracter - o espaço. |"
echo "+------------------------------------------------------+"
echo "|Exemplos: Seu campo de texto para usar no Script é de |"
echo "|20 caracteres. No banco esta com 17 apenas. |"
echo "|Meu texto exemplo. Quando completar ficará: |"
echo "|Meu texto exemplo... |"
echo "+------------------------------------------------------+"
echo "|A informação do banco vem com 25 caracteres. |"
echo "|Meu texto é muito grande. |"
echo "|Ficará assim: Meu texto é muito... |"
echo "+------------------------------------------------------+"
read -t 10
exit
fi
# Valida o recebimento de parâmetros de forma controlada.
if [ "$#" -gt 2 ]
then
# Variáveis de trabalho.
_tt="$1" # Tamanho que o texto deverá retornar.
_var_tmp="$2" # Texto recebido
_completar="$3" # caracter que será usado no completar.
# Avalia se o 1º parâmetro é um número.
if [ $((_tt)) -gt 0 ]
then
# Confere se realmente enviou apenas 1 caracter.
# Se enviou mais de 1 caracter, não sabe o que faz.
if [ "${#_completar}" -gt 1 ]
then
echo "Só pode receber 1 caracter para completar"
echo "Veja o que você está fazendo com: $3"
sleep 5
return 1 # Erro grave.
fi
# Forçando a verificação do tamanho recebido.
# Se ele for >= ao total, será cortada.
if [ "${#_var_tmp}" -ge "${_tt}" ]
then
_var_tmp=${_var_tmp:0:_tt-3}
fi
# Executando o complemento do texto solicitado.
_vl_texto=${#_var_tmp}
_falta=$((_tt - _vl_texto))
i="1"
_tmp_texto=$_completar
while test $i -lt $_falta
do
let i++
_tmp_texto="${_tmp_texto}${_completar}"
done
# Efetua o preenchimento a direita ou esquerda.
# Parâmetro é opcional. Default é completar a direita.
if [ "$4" = "E" ]
then
_texto_completo="${_tmp_texto}${_var_tmp}"
else
_texto_completo="${_var_tmp}${_tmp_texto}"
fi
echo "${_texto_completo}"
else
clear
echo "+-------------------------------------------+"
echo "| Este parâmetro tem que ser numérico: $_tt * "
echo "| Verifique o que você está errado. |"
echo "| Texto será retornado sem alterações |"
echo "| Por este motivo, se vira nos 30 zé. |"
echo "+-------------------------------------------+"
echo "$_var_tmp"
read -t 5
return 1 # Retornando erro pro zé.
fi
else
clear
echo "+------------------------------------------------------+"
echo "|Não enviou a quantidade de parâmetros correta !!! |"
echo "+------------------------------------------------------+"
echo "|1º) Numérico. Indica o tamanho que o texto ficará |"
echo "|2º) String do texto ou valor do texto a completar. |"
echo "|3º) Qual o caracter que será usado para completar. |"
echo "|4º) Completa Char. 'D'ireita ou 'E'squerda,opcional. |"
echo "+------------------------------------------------------+"
echo "|Operação não será efetuada até acerto dos parâmetros. |"
echo "+------------------------------------------------------+"
read -t 5
return 1 # Indica que houve um erro fatal.
fi
}
# Tabela de preços. Usada para consulta e busca.
# Ficou até bacana a forma de gravar. Peca no posicionamento dos valores.
function tabela_de_precos()
{
# Pegar o arquivos cardapio.txt e trabalhar seus dados no formato.
# Tentar fazer ele ser aproveitado em rotinas posteriores.
while read linha;do
# Monto um array para usar como tabela e indexador para seek.
# Tratar valores de campo para compor a linha formatada.
cod_prod=$(echo $linha | cut -d: -f2)
pre_prod=$(echo $linha | cut -d: -f3)
nom_prod=$(echo $linha | cut -d: -f1)
nom_completo=$(completa_texto 30 "${nom_prod}" ".")
# Armazenar só preços.
tab_precos[${cod_prod}]="${cod_prod}:${nom_completo}:${pre_prod}"
# FIXME: variável #POG para contornar tamanho de impressão.
tp="6"
# Só mostra na tela caso não seja chamado pelo processo de carga.
if [ "$1" = "carga" ]
then
:
else
printf "%0s%-31s%-$((${#pre_prod} - ${tp}))s%-5s%-10s\n" \
"|$cod_prod|" " $nom_completo" "|" "$pre_prod|"
fi
done < "$_FILE_CARDAPIO" # Usa arquivo parametrizado.
}
# Tela genérica para o cardápio. Note que trabalha sempre em memória.
function cardapio()
{
clear
echo "+=========================================+"
echo "|Cardápio lanchonete modelo Canabrava |"
echo "+=========================================+"
echo ""
echo "+---+-------------------------------+-----+"
echo "|Cod| Produto |Preço|"
echo "+---+-------------------------------+------"
tabela_de_precos
echo "+---+------------------------------.+-----+"
echo -n "Enter retorna onde você estava "
read
}
# Sem novidade. Tela central do menu. É reaproveitado em vários locais.
function mostramenu()
{
clear
echo "========================================"
echo "Menu Principal"
echo "========================================"
echo ""
echo "c - Mostra Cardápio"
echo "d - Digitar pedido"
echo "l - Lista o pedido"
echo "f - Finaliza o pedido"
echo "s - Sair"
echo "h - Ajuda"
echo ""
if [ "$1" ]; then echo -n "Escolha a opção:" ; fi
}
# Esta função não ajuda patavinas, rrs, mas serve de exemplo como fazer.
# Se for o caso, a aplicação pode montar parâmetros e tratar este local.
function ajuda()
{
echo ""
echo "+------------------------------------+"
echo "|Coloque aqui as opções de ajuda |"
echo "|Dicas de uso para o protosuário !!! |"
echo "+------------------------------------+"
read -t 5
return
}
# Generalizando as opções para ser reaproveitada em mais de um local.
function _opcoes()
{
# Recebe 1 parâmetro para saber o local onde está. exemplos:
# Menu principal é escolha. "$escolha", na Digitação é "$numero"
case "$1" in
c) cardapio ;;
d) digitar ;;
l) listar ;;
f) finaliza ;;
s) sair ;;
h) ajuda ;;
*) erro ;;
esac
}
function _menu()
{
clear
while true
do
mostramenu normal
read escolha
_opcoes "$escolha"
done
}
# O sistema só vai trabalhar se encontrar a tabela do cardápio.
function achou_tabela()
{
if test -e "${_FILE_CARDAPIO}"
then
# Achou a tabela com o cardápio, vai trabalhar.
tabela_de_precos carga # Força carregar a tabela de preços.
else
# Falhou a busca pelo arquivo, sistema irá abortar.
echo ""
echo "+------------------------------------+"
echo "|Não encontrou a tabela do cardápio: |"
echo "|Config: ${_CONF_CARDAPIO} |"
echo "+------------------------------------+"
read -t 5
exit
fi
}
function main()
{
achou_tabela # Verifica a existência da tabela do cardápio.
_menu # Menu principal
}
main "${@#}"
exit
#################### "Quem pergunta é bobo por 5 minutos..." #########
######## "Quem não pergunta é bobo para sempre! (Provérbio Chinês)" ##
######################################################################