shell script to check if input is a string/integer/float

#!/bin/bash
read -p "Enter value:" val
echo "$val"|grep "^[0-9]*$"
val="$?"
if [[ $val == 0 ]]
then
echo "Integer"
exit
fi
echo $val|grep "^[a-zA-Z]*$"
val="$?"
if [[ $val == 0 ]]
then
echo "String"
exit
fi
echo $val|grep "^[0-9]*.[0-9]*$"
val="$?"
if [[ $val == 0 ]]
then
echo "Float"
exit
fi

If I enter a string like "ape" it says "grep invalid range" and then prints float. Where did I go wrong?

2

4 Answers

This bash code returns integer for integers like 123, float for floating point numbers like 123.4 and string for any other input values like "123", One23 123. or 123.4.5.

#!/bin/bash
read -p "Type a number or a string: " input
if [[ $input =~ ^[+-]?[0-9]+$ ]]; then
echo "Input is an integer."
elif [[ $input =~ ^[+-]?[0-9]+\.$ ]]; then
echo "Input is a string."
elif [[ $input =~ ^[+-]?[0-9]+\.?[0-9]*$ ]]; then
echo "Input is a float."
else
echo "Input is a string."
fi
5

I can't reproduce your error, but since it's complaining about an invalid range, it's most likely a locale issue. Try running your script again, but setting the locale:

LC_ALL=C yourscript.sh

Of course, that won't fix the other problem which is:

echo $val|grep "^[a-zA-Z]*$"
val="$?"

After those lines, $val is no longer the value you gave, it is now the exit status of the grep, so everything after that is testing the wrong thing.


In any case, this is really needlessly complex. All you really need is:

#!/bin/bash
val="$@"
[[ -z $val ]] && echo "No input!" && exit
if [[ "$val" =~ ^[+-]?[0-9]+$ ]]; then echo "Number!"
elif [[ $val =~ ^[+-]?[0-9]*\.[0-9]+$ ]]; then echo "Float!"
elif [[ $val =~ [0-9] ]]; then echo "Mixed, some numbers"
else echo "No numbers!"
fi 

Note that I'm using val="$@" instead of read. This means you can now run your script as yourscript.sh input instead of having to type out the input every time. That way, you can see what you did in the history, you avoid typing errors, you can run the script automatically etc. It is generally a bad idea to use read and force your users to enter input.

Also note that I changed some of your terms. I now consider 4 possibilities:

  1. The input has nothing but numbers: print "Number" (whether 001002 is an integer depends on what sort of maths you're thinking of).
  2. The input consists of 0 or more numbers, then a dot and then nothing but numbers (0 or more because .2 can be considered valid in some cases; if you don't want that, change the ^\d*\.\d+$ to ^\d+\.\d+$).
  3. The input has numbers but not only numbers: print "Mixed, some numbers". Note that this will also catch 1. which is not a valid float and not a valid integer.
  4. The input has no numbers: print "No numbers".

I split 3 and 4, but you can join them and have them print the same, if you like.

Also, kudos to Karel for thinking of +N and -N numbers.

What about using the 'test' command side effect? Weighting a string suspect of being an integer, like 123, with e.g. 0 for equality returns 0 (true) or 1 (false) or 2 (error). This tells you directly whether string is worth comparing, i.e. if it is a valid integer representation:

[ $str2test -eq 0 ] 2>/dev/null
if [ $? -lt 2 ] then \# Correct integer representation ... else \#Incorrect integer representation ...
fi
!/bin/bash
read -p "Enter value:" val
echo "$val"|grep "^[0-9]*$"
val="$?"
if [[ $val == 0 ]]
then
echo "Integer"
exit
fi
echo $latter|grep "^[a-zA-Z]*$"
latter="$?"
if [[ $latter == 0 ]]
then
echo "String"
exit
fi

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like