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)" ## 
######################################################################