How to Validate Integer Input using Shell script

validating integer input seems like a breeze until you want to ensure that negative values are acceptable too. The problem is that each numeric value can have only one negative sign, which must come at the very beginning of the value. The validation routine in this script makes sure that negative numbers are correctly formatted, and, to make it more generally useful, it can also check that values are within a range specified by the user.

The Code
#!/bin/sh
# validint -- Validates integer input, allowing negative ints too.

function validint
{
# Validate first field. Then test against min value $2 and/or
# max value $3 if they are supplied. If they are not supplied, skip these tests.

number="$1"; min="$2"; max="$3"

if [ -z $number ] ; then
echo "You didn't enter anything. Unacceptable." >&2 ; return 1
fi

if [ "${number%${number#?}}" = "-" ] ; then # is first char a '-' sign?
testvalue="${number#?}" # all but first character
else
testvalue="$number"
fi

nodigits="$(echo $testvalue | sed 's/[[:digit:]]//g')"

if [ ! -z $nodigits ] ; then
echo "Invalid number format! Only digits, no commas, spaces, etc." >&2
return 1
fi

if [ ! -z $min ] ; then
if [ "$number" -lt "$min" ] ; then
echo "Your value is too small: smallest acceptable value is $min" >&2
return 1
fi
fi
if [ ! -z $max ] ; then
if [ "$number" -gt "$max" ] ; then
echo "Your value is too big: largest acceptable value is $max" >&2
return 1
fi
fi
return 0
}

Running the Script
This entire script is a function that can be copied into other shell scripts or included as a library file. To turn this into a command, simply append the following to the bottom of the script:

if validint "$1" "$2" "$3" ; then
echo "That input is a valid integer value within your constraints"
fi


The Results
$ validint 1234.3
Invalid number format! Only digits, no commas, spaces, etc.
$ validint 103 1 100
Your value is too big: largest acceptable value is 100
$ validint -17 0 25
Your value is too small: smallest acceptable value is 0
$ validint -17 -20 25
That input is a valid integer value within your constraints

Hacking the Script
Notice in this script the following test to see if the number's first character is a negative sign:

if [ "${number%${number#?}}" = "-" ] ; then

If the first character is a negative sign, testvalue is assigned the numeric portion of the integer value. This nonnegative value is then stripped of digits, and what remains is tested further.

You might be tempted to use a logical AND to connect expressions and shrink some of the nested if statements. For example, it seems as though the following should work:

if [ ! -z $min -a "$number" -lt "$min" ] ; then
echo "Your value is too small: smallest acceptable value is $min" >&2
exit 1
fi