1

I wanted to simulate a vending machine where you can buy things only if you throw 2€ inside.

It works as long as i only enter integer values, but if i enter a character or a float it suddenly stops to work. And throws an error that there is an integer expression expected.

read -p "Throw in money" x
echo ""

while [ $x -ne 2 ] ;
do
case $x in
        0.5)
                read -p "more money" z
                x=$(($x + $z))
                ;;
        1)
                read -p "more money" z
                x=$(($x + $z))
                ;;
        1.5)
                read -p "more money" z
                x=$(($x + $z))
                ;;
        "R")
                echo "return x"
                x=0
                ;;
        ?)
                echo "enter something else!"
                x=0
                ;;
esac
done
1
  • How can you input a string when you are checking against an integer in the while expression Commented May 18, 2017 at 10:30

3 Answers 3

2

-ne only does integer comparisons, so $x must expand to something that the shell recognizes as an integer. Just switch to != and compare as a string. Further, since bash cannot add floating point values either, you'll need to use something like bc to do the addition.

while [ "$x" != 2 ] ;
do
  case $x in
        0.5)
                read -p "more money" z
                x=$( bc <<< "$x + $z" )
                ;;
        1)
                read -p "more money" z
                x=$( bc <<< "$x + $z" )
                ;;
        1.5)
                read -p "more money" z
                x=$( bc <<< "$x + $z" )
                ;;
        "R")
                echo "return x"
                x=0
                ;;
        ?)
                echo "enter something else!"
                x=0
                ;;
  esac
done
Sign up to request clarification or add additional context in comments.

1 Comment

That doesn't help much, since Bash still can only do arithmetic with integers
0

One approach is to use a regular expression, like so:

re='^[0-9]+$'
if ! [[ $yournumber =~ $re ]] ; then
   echo "error: Not a number" >&2; exit 1
fi

Comments

0

Bash can only do arithmetic with integers, as stated in the manual.

To do floating point arithmetic, you'd need to do something like piping to bc:

$ x=1.0; z=0.5
$ bc <<< "$x + $z"
1.5

Comparisons work, sort of, you need to read the output to get the truth value:

$ bc <<< "$x < 1.5"
1

Other choices would be to convert the floats to another internal representation, e.g. counting cents instead of full dollars/euros. Or convert the script to something like zsh, awk or Perl, which can deal with floats.


Here's a sketch for cent-based counting:

#!/bin/bash
total=0
getcoin() {

        read -p "Insert coin: " x
        case $x in
        0.1)    cents=10 ;;
        0.2)    cents=20 ;; 
        0.5)    cents=50 ;;
        1|1.0)  cents=100 ;;
        2|2.0)  cents=200 ;;
        *)      echo "Invalid coin!"; return 0;;
        esac
        (( total = total + cents))
        return 0;
}

while getcoin && [[ $total -lt 200 ]] ; do
        printf "You have %d cents\n" "$total"
done
printf "You got %d.%02d € in total\n" $((total / 100)) $((total % 100))

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.