0

I don't know why, but only the '0' option works, unless the 'clear' command is removed or commented out. See the script:

NUMERO=-1
while [ $NUMERO -ne 0 ]; do
    clear
    echo "------ M E N U ------"
    echo "1 - Primeira opção"
    echo "2 - Segunda opção"
    echo "3 - Terceira opção"
    echo "0 - Sair"

    while true; do
        read -p "Opção: " NUMERO
        [[ -n "$NUMERO" ]] && break
    done

    if [ $NUMERO == 1 ]; then
        echo "Você escolheu a opção $NUMERO"        
    elif [ $NUMERO == 2 ]; then
        echo "Você escolheu a opção $NUMERO"
    else
        echo "Você escolheu a opção $NUMERO"
    fi
done

After adding 'exec 3>trace.log; BASH_XTRACEFD=3; set -x' to the beginning of the script, I got the following content in the trace.log file:

+ NUMERO=-1
+ '[' -1 -ne 0 ']'
+ clear
+ echo '------ M E N U ------'
+ echo '1 - Primeira opção'
+ echo '2 - Segunda opção'
+ echo '3 - Terceira opção'
+ echo '0 - Sair'
+ true
+ read -p 'Opção: ' NUMERO
+ [[ -n 1 ]]
+ break
+ '[' 1 == 1 ']'
+ echo 'Você escolheu a opção 1'
+ '[' 1 -ne 0 ']'
+ clear
+ echo '------ M E N U ------'
+ echo '1 - Primeira opção'
+ echo '2 - Segunda opção'
+ echo '3 - Terceira opção'
+ echo '0 - Sair'
+ true
+ read -p 'Opção: ' NUMERO
+ [[ -n 0 ]]
+ break
+ '[' 0 == 1 ']'
+ '[' 0 == 2 ']'
+ echo 'Você escolheu a opção 0'
+ '[' 0 -ne 0 ']'
8
  • Add exec 3>trace.log; BASH_XTRACEFD=3; set -x to the top of your script, then edit the contents of trace.log into the question. (Make sure you're actually running it with bash, not sh, and that the bash version is 4.3 or later for that logging to work). Commented Mar 30 at 12:45
  • BTW, there are some obvious bugs, though it's not clear that clear would have anything to do with triggering them. == isn't a POSIX-standardized string comparison operator -- only = is guaranteed to work on shells that implement only bare-minimum POSIX functionality. And make sure you compare "$NUMERO" not $NUMERO. Additionally, consider making a habit of using lowercase names for your own variables -- all-caps names are used by names meaningful to the shell and OS-provided tools, so by using lowercase names you ensure that you aren't changing other components' behavior by mistake. Commented Mar 30 at 12:47
  • To be clear, in other situations clear can modify $? and thus modify control flow, but that's not the case in the specific script you show here. You've got some kind of a side effect going on -- maybe something wrong with your terminal where the control sequences are influencing following input? -- but we can't diagnose it without further details. Commented Mar 30 at 13:00
  • 1
    Maybe add a sleep 1 at the end of the loop so there's a delay before it goes back to the top? Commented Mar 30 at 13:25
  • 1
    As an aside, you might want to read up on the select command. Commented Mar 30 at 13:37

1 Answer 1

0

POSIX shell menu

Here is how I will do this:

No, clear won't affect your input!

#!/bin/sh

number=-1
while true; do
    clear
    echo "------ M E N U ------"
    echo "1 - Primeira opção"
    echo "2 - Segunda opção"
    echo "3 - Terceira opção"
    echo "0 - Sair"

    while true; do
        printf 'Opção: '
        read -r number
        case $number in
                ''|*[!0-9]* )
                        echo "Input '$number' is not a number."
                        ;;
                * )
                        break
                        ;;
        esac
    done
    case $number in
            0 | 1 | 2 | 3 ) break ;;
    esac
    echo "Input $number is not in menu!"
    sleep 1.5 # time to read previous message before next `clear`.
done
echo "Você escolheu a opção $number"        
  • I use case for testing input is a number, from: How do I test if a variable is a number?
  • I use case for main exit before it's a lot simpler and efficient than if .. elif ... fi.
  • Added a sleep at end of loop, in order to permit user to read message before clear will be executed.

POSIX shell menu, using dialog or equivalents

From How do I prompt for Yes/No/Cancel input in a Linux shell script?

#!/bin/sh

number="$(
     dialog --menu 'Menu' 20 60 6 1 "Primeira opção" 2 "Segunda opção" \
         3 "Terceira opção" 0 "Sair" 2>&1 >/dev/tty
)"
echo "Você escolheu a opção $number"

dialog menu

POSIX shell menu, using fzf

Or using recent fzf utility:

#!/bin/sh

number="$(
  printf '0 - Sair\n3 - Terceira opção\n2 - Segunda opção\n1 - Primeira opção'|
      fzf)"

echo "Você escolheu a opção ${number%% *}"

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.