Question

I'm relatively new to bash programming and i am currently creating a simple calculator.

It needs to use floating point numbers and check they are so.

I have a checkNumbers function:

function checkNumber {

    regExp=[0-9]

    if [ $testNo =~ $regExp ]
    then
        echo "That is a number!"
        let check=1
    else
        echo "Damn! Not A Number!"
    fi
}

where i get the user to input a number like this:

while [ $check -eq 0]
do
    echo "Please enter a number
    read testNo
    echo ""
    checkNumber
done

This does not work, i get this error:

./calculator.sh: line 39: [: =~: binary operator expected

line 39 is:

if [ $testNo =~ $regExp ] 

I have tried lots of Regular Expressions like:

^*[0-9]*$

and

^*[0-9]\.[0.9]*$

etc etc.

also, i have tied other ways of performing the check:

case $testNo
in
    ^*[0-9]*$) echo "That is a number!";;
    *) echo "Error! Not a number!";;
esac

and

if [ $testNo = ^*[0-9]*$ ]
then
    echo "etc etc"
else
    echo "oops"
fi

I also need this to work with floating point numbers.

could someone please let me know how i go about this?

Was it helpful?

Solution

This regex ^[-+]?[0-9]+\.?[0-9]*$ will match only digits with an optional .:

$ echo 30 | grep -Eq '^[-+]?[0-9]+\.?[0-9]*$' && echo Match
Match

$ echo 30.10 | grep -Eq '^[-+]?[0-9]+\.?[0-9]*$' && echo Match
Match

$ echo 30. | grep -Eq '^[-+]?[0-9]+\.?[0-9]*$' && echo Match
Match

$ echo +30 | grep -Eq '^[-+]?[0-9]+\.?[0-9]*$' && echo Match
Match

$ echo -30 | grep -Eq '^[-+]?[0-9]+\.?[0-9]*$' && echo Match
Match

I think when you tried ^*[0-9] you wanted ^[0-9]*

Rexeplanation:

^       # Match start of string
[-+]?   # Match a leading + or - (optional)
[0-9]+  # Match one or more digit
\.?     # Match a literal . (optional, escaped)
[0-9]*  # Match zero or more digits
$       # Match the end of the string

Note: this matches numbers followed by a . like 30., not sure if this is acceptable for you.

Edit: Don't quote the regex

testNo=30.00

if [[ $testNo =~ ^[+-]?[0-9]+\.?[0-9]*$ ]]; then 
    echo Match
fi

>>> Match

OTHER TIPS

To use that type of feature, you need the [[ ... ]] version of the conditional. [ is the "old" test command and doesn't handle regular expressions at all.

#! /bin/bash
function checkNumber {
    regExp='^[+-]?([0-9]+\.?|[0-9]*\.[0-9]+)$'
    if [[ $testNo =~ $regExp ]]
    then
        echo "That is a number!"
        let check=1
    else
        echo "Damn! Not A Number!"
    fi
}
testNo=1
checkNumber
testNo=-1.2
checkNumber
testNo=+.2
checkNumber
testNo=+0.
checkNumber
testNo=a
checkNumber
testNo=hello2you
checkNumber

$ ./t.sh
That is a number!
That is a number!
That is a number!
That is a number!
Damn! Not A Number!
Damn! Not A Number!

See What is the difference between test, [ and [[ ?.

An explanation on the regex:

^ Anchor at start of string
$ Anchor at end of string

These two make the regex match the whole string passed, partial matches are not allowed.

[+-]

matches either + or -.

[+-]?

makes that part optional, so the above matches exactly +, - or nothing at all.

Then there's an alternation (part1|part2) which will match if part1 or part2 matches.

Part one is:

[0-9]+\.?

which matches one or more (+) digits (but not zero digits/empty set) and an optional .. This handles numbers of the form 123 and 534.. But not just ..

Part two is:

[0-9]*\.[0-9]+

This matches zero or more (*) digits, followed by a ., followed by one or more digits. This matches all other floats like 1.3 or .543 (without exponent notation), but still excludes just ..

#!/bin/bash
#script to validate 

while [ true ]; do
clear
echo "Introduce the numeric value: "
read -r var
if [[ $var =~ ^[+-]?([0-9]+)$ ]]
   then
      echo "You introduced an integer value (without decimals)"
      read
   else
      if [[ $var =~ ^[+-]?([0-9]+\.)$ ]]
         then
            echo "Incomplete floating value (no values provided at the right of the point)"
            read
         else
            if [[ $var =~ ^[+-]?(\.[0-9]+)$ ]]
               then
                  echo "Incomplete floating value (no values provided at the left of the point)"
                  read
               else
                  if [[ $var =~ ^[+-]?([0-9]+\.[0-9]+)$ ]]
                     then
                        echo "You introduced a correct floating value"
                        read
                     else
                        echo "You introduced something other than a valid numeric value"
                        read
                  fi
            fi
      fi
fi
done

I include an optional dot at the start.

       user@debian:~$ testNo=.01
       user@debian:~$ if [[ $testNo =~ ^[+-]?[.]?[0-9]+\.?[0-9]*$ ]]; 
                    > then         
                    > echo Match; 
                    > fi
         Match
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top