0

I have bash script with basic arithmetic operations - Addition, Subtraction, Division and Multiplication.

    #! bin/bash

input="yes"
while [[ $input = "yes" ]]
do

    PS3="Press 1 for Addition, 2 for subtraction, 3 for multiplication and 4 for division: "
    select math in Addition Subtraction Multiplication Division
    do
        case "$math" in
        Addition)
            echo "Enter first no:"
            read num1
            echo "Enter second no:"
            read num2
            result=`expr $num1 + $num2`
            echo Answer: $result
            break
        ;;
        Subtraction)
            echo "Enter first no:"
            read num1
            echo "Enter second no:"
            read num2
            result=`expr $num1 - $num2`
            echo Answer: $result
            break
        ;;
        Multiplication)
            echo "Enter first no:"
            read num1
            echo "Enter second no:"
            read num2
            result=`expr $num1 * $num2`
            echo Answer: $result
            break
        ;;
        Division)
            echo "Enter first no:"
            read num1
            echo "Enter second no:"
            read num2
            result=$(expr "scale=2; $num1/$num2" | bc)
            echo Answer = $result
            break
        ;;
        *)
            echo Choose 1 to 4 only!!!!
            break
        ;;
    esac
    done

done

How to make that values for @num1 and @num2 are accepted only if they are numbers in certain range. For example 0 to 10. So if I enter for $num1 or $num2 lets say 500 there will be message to enter valid value?

5
  • What have you tried? You should be able to come up with a test that you can use to break out of the case statement with a message. This might be a good candidate for a function. Commented May 7, 2018 at 18:27
  • Are the numbers only integers? Commented May 7, 2018 at 18:42
  • @PesaThe, yes they are. Commented May 7, 2018 at 18:45
  • while (( $num1 < 0 || $num1 > 10 )); do read -p'Number must be between 0 and 10.' num1; ... done Commented May 7, 2018 at 18:50
  • expr is antiquated pre-POSIX syntax. Use result=$((num1 * num2)) for math in modern POSIX-compliant shells. The expr syntax requires forking a subshell, setting up a pipeline to read that subshell's output, executing an external binary, read()ing its output, wait()ing to collect its exit status, etc; the native syntax just does the math internally to the bash executable. Commented May 7, 2018 at 19:24

1 Answer 1

2

You can create a simple function to get a number in range:

get_number() {
    local lo=$1 up=$2 text=${3:-Enter a number: } num      
    shopt -s extglob

    until   
        read -p "$text" num
        [[ $num = ?(-)+([0-9]) ]] && (( $lo <= 10#$num && 10#$num <= $up ))
    do
        echo "Invalid input!" >&2
    done
    echo "$((10#$num))"
}

num1=$(get_number 10 15 "Enter first number: ")
num2=$(get_number -10 20) # use default prompt

Works for integers only. You might also consider inputting the numbers before the case command to avoid redundant code.

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

4 Comments

and shopt -s extglob is required.
@glennjackman thanks for the tip. Is extglob required? Perhaps in older versions but quoting manual: ...matched according to the rules described below in Pattern Matching, as if the extglob shell option were enabled..
That behavior is indeed version-dependent; safer to enable the flag for compatibility.
@CharlesDuffy I see. Thanks.

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.