[Dúvida] Menu em shell script

Galera, conhecem um jeito + simples do que usar o case para elaborar um menu no script?

Exemplo do uso de case:

#!/bin/bash

Menu() {
clear
echo " Opções:"
echo " 1."
echo " 2."
echo " 3."
echo " A."
echo " B."
echo " C."
echo
echo -n "Esolha uma opção: "
read OPTION
echo
case $OPTION in
    1) echo "Você escolheu a opção 1" ;;
    2) echo "Você escolheu a opção 2" ;;
    3) echo "Você escolheu a opção 3" ;;
    a|A|"") echo "Você escolheu a opção A" ;;
    b|B|"") echo "Você escolheu a opção B" ;;
    c|C|"") echo "Você escolheu a opção C" ;;
    *) echo "Opção inválida" ;;
esac

echo
echo -n "Sair? [S/N] "
read SAIR
echo
case $SAIR in
    s|S|"") exit ;;
    n|N|"") Menu ;;
    *) echo "Opção inválida" ;;
esac
}

Menu
1 Curtida

Para simplificar e compactar os códigos, utilizando o case, podes ser inspirado pelo còdigo-fonte feito pelos desenvolvedores do Oomox e do Papirus para mim:

1 Curtida

Obgdo pela dica @gusbemacbe, mas n tenho noção de como fazer isso. Nunca utilizei o declare pra algo, talvez pelo fato de até hoje ter programado scripts simples.

1 Curtida

Não sabia que estás a começar a aprender, desculpe-me, embora isto possa ser-te útil, mesmo sendo iniciante.

1 Curtida

Declare é só por boas práticas não tem segredo o seu uso

1 Curtida

Não me parece algo tão simples, eu olhei o código e não consegui nem supor como usar este comando no meu script. Tenho grande dificuldade em aprender a programar, as vezes algo pode fazer algum sentido pra mim, outras vezes não. É como a matemática, dificilmente conseguia compreender a lógica por trás de uma fórmula.

2 Curtidas

Tecnicamente não é um comando, tira o declare -a do comando dele, é só um array simples do bash:

declare <tipo> <flags> <nome da variável>=<valor>

 <Tipo> pode ser:

-a que indica um array
-i um um número inteiro 

Sem especificar o tipo ele se torna uma string  (texto com qualquer tipo de caractere)

<flags> considerando 99% das vezes que se usa:

-r torna a variável constante
-x torna a variável visível a todos os comandos executados a partir da li (equivale ao export)
-g torna a váriavel visível fora da função (variável global)

Até tem outras mas são irrelevantes nesse contexto 

Porque se usa?

Bash Sceipt é uma linguagem com tipos dinâmicos ou seja você pode fazer:

X=123

E depois

X=“abc”

Que o bash vai aceitar numa boa, isso pode ser problemático em algumas situações, o declare permite forçar uma variável a aceitar apenas um tipo de dado causando um erro se em algum momento você ou algum comando mudar o tipo da variável. Outra função é impedir que o valor que a variável possui seja alterado. De resto a declaração fica exatamente igual ao modo “tradicional”

1 Curtida

Sim, usando a comparação em linha do bash e usando o operador && ( comando após esses dois caracteres só será executado se o código de saída do anterior for 0), o certo é padronizar ou seja, usar ou letras ou números, no caso vou assumir que as opções A, B e C serão os números 4, 5 e 6respectivamente pra facilita, a função menu ficaria assim:

clear
echo " Opções:"
echo " 1."
echo " 2."
echo " 3."
echo " 4."
echo " 5."
echo " 6."
echo
echo -n "Esolha uma opção: "

read -n1 -s OPTION
# -n1 faz com que o usuário só possa digitar um caractere por vez
# -s faz com que o read não mostre o que o usuário digitou

[[ "$OPTION" =~ ^[0-9]+$ ]] || OPTION=0
# Verifica se OPTION começa (^) e termina ($) 
# com um numero entre 0 e 9 ([0-9]+)
# Se não (||) OPTION receberá 0 como valor

[ "$OPTION" -ge 1 -a "$OPTION" -le 6 ] || OPTION=0
# Verifica se  OPTION é maior ou igual (-ge) a 1
# e\ou (-a) menor ou igual a (-le) 6 
# (6 é a quantidade de opções) 
# Se não (||) OPTION receberá 0 como valor

[ "$OPTION" = "1" ] && echo "Você escolheu a opção 1" 
[ "$OPTION" = "2" ] && echo "Você escolheu a opção 2" 
[ "$OPTION" = "3" ] && echo "Você escolheu a opção 3"
[ "$OPTION" = "4" ] && echo "Você escolheu a opção 4"
[ "$OPTION" = "5" ] && echo "Você escolheu a opção 5"
[ "$OPTION" = "6" ] && echo "Você escolheu a opção 6"
[ "$OPTION" = "0" ] && echo "Opção inválida"
# Aqui  ocorre o contrario:
# Se OPTION for igual (=) a um número das opções 
# então (&&) execute a ação...
# o que faz o tratamento se a opção for invávalida
# é quando ela for igual a 0

Note que se vocẽ souber como && e || funcionam fica bem mais légivel

1 Curtida

Uma coisa que você pode fazer (quando ficar um pouco mais avançado porque envolve laços de repetição e manipulação de arrays) é transformar a função menu em uma “geradora” de menus padronizada, por exemplo:

function menu() {
  ESCOLHA=""
  clear
  contador=1
  echo "------------------------------------"
  echo "  $1"
  shift
  ITEMS=${@}
  echo -e "------------------------------------\n"
  for i in "${@}"; do
     echo "  [ $contador ]  $i"
     contador=$(($contador+1))
  done
  echo -e "\n------------------------------------\n"
  echo "  Pressione a tecla com o número"
  echo -e "  que corresponde a sua escolha:\n"
  read -s -n1 ESCOLHA
  [[ "$ESCOLHA" =~ ^[0-9]+$ ]] || ESCOLHA=0
  [ "$ESCOLHA" -ge 1 -a "$ESCOLHA" -le $contador ] || ESCOLHA=0
}

Assim você pode chamar os menus assim:


menu "Escolha um prato" "Arroz com frango" "Lasanha" "Pizza"
[ "$ESCOLHA" = "0" ] && echo "Resposta inválida"
[ "$ESCOLHA" = "1" ] && echo "Arroz com frango é muito bom"
[ "$ESCOLHA" = "2" ] && echo "Lasanha é uma boa pedida"
[ "$ESCOLHA" = "3" ] && echo "Não gosto de Pizza"

read -n1 -s -p "Pressione uma tecla para continuar..."
# Por causa do comando "clear"


# E novamente: 

menu "Escolha um animal" "Gato" "Cachorro" "Papagaio"
[ "$ESCOLHA" = "0" ] && echo "Resposta inválida"
[ "$ESCOLHA" = "1" ] && echo "Gatos são animais selvagens"
[ "$ESCOLHA" = "2" ] && echo "Cachorros são parentes dos lobos"
[ "$ESCOLHA" = "3" ] && echo "Papagaios são aves"

A saída fica assim no caso da primeira chamada:

------------------------------------
  Escolha um prato
------------------------------------

  [ 1 ]  Arroz com frango
  [ 2 ]  Lasanha
  [ 3 ]  Pizza

------------------------------------

  Pressione a tecla com o número
  que corresponde a sua escolha:

2 Curtidas