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?
A regular expression matching sign, the =~ operator, is used to identify regular expressions. Perl has a similar operator for regular expression corresponding, which stimulated this operator.
You can use the test construct, [[ ]] , along with the regular expression match operator, =~ , to check if a string matches a regex pattern (documentation). where commands after && are executed if the test is successful, and commands after || are executed if the test is unsuccessful.
[0-9]*. This defines a floating point number as an optional sign, followed by an optional series of digits (integer part), followed by an optional dot, followed by another optional series of digits (fraction part).
To match any number from 0 to 9 we use \d in regex. It will match any single digit number from 0 to 9. \d means [0-9] or match any number from 0 to 9. Instead of writing 0123456789 the shorthand version is [0-9] where [] is used for character range.
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
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 .
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With