Checking if an input number is an integer
205,829
Solution 1
Remove quotes
if ! [[ "$scale" =~ ^[0-9]+$ ]]
then
echo "Sorry integers only"
fi
Solution 2
Use -eq
operator of test command:
read scale
if ! [ "$scale" -eq "$scale" ] 2> /dev/null
then
echo "Sorry integers only"
fi
It not only works in bash
but also any POSIX shell. From POSIX test documentation:
n1 -eq n2
True if the integers n1 and n2 are algebraically equal; otherwise, false.
Solution 3
As the OP seems to want only positive integers:
[ "$1" -ge 0 ] 2>/dev/null
Examples:
$ is_positive_int(){ [ "$1" -ge 0 ] 2>/dev/null && echo YES || echo no; }
$ is_positive_int word
no
$ is_positive_int 2.1
no
$ is_positive_int -3
no
$ is_positive_int 42
YES
Note that a single [
test is required:
$ [[ "word" -eq 0 ]] && echo word equals zero || echo nope
word equals zero
$ [ "word" -eq 0 ] && echo word equals zero || echo nope
-bash: [: word: integer expression expected
nope
This is because dereferencing occurs with [[
:
$ word=other
$ other=3
$ [[ $word -eq 3 ]] && echo word equals other equals 3
word equals other equals 3
Solution 4
For unsigned integers I use:
read -r scale
[ -z "${scale//[0-9]}" ] && [ -n "$scale" ] || echo "Sorry integers only"
Tests:
$ ./test.sh
7
$ ./test.sh
777
$ ./test.sh
a
Sorry integers only
$ ./test.sh
""
Sorry integers only
$ ./test.sh
Sorry integers only
Solution 5
A POSIX and portable solution is:
read scale
if [ -z "${scale##*[!0-9]*}" ];
then echo "Sorry integers only"
fi
Related videos on Youtube
Author by
lonewarrior556
Updated on September 18, 2022Comments
-
lonewarrior556 almost 2 years
I'm trying to check if an input is an integer and I've gone over it a hundred times but don't see the error in this. Alas it does not work, it triggers the if statement for all inputs (numbers/letters)
read scale if ! [[ "$scale" =~ "^[0-9]+$" ]] then echo "Sorry integers only" fi
I've played around with the quotes but either missed it or it did nothing. What do I do wrong? Is there an easier way to test if an input is just an INTEGER?
-
lonewarrior556 almost 10 yearsthat checks if its any number, not just integers
-
cuonglm almost 10 years@lonewarrior556: It works only for integer, see: pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html. I guess you said for any number because you use new test
[[
instead of old test[
as mine. -
lonewarrior556 almost 10 yearsstackoverflow.com/questions/806906/… had the quotes backwards
-
Wildcard over 7 yearsGood idea but a bit noisy. I would rather not have to redirect errors to dev null.
-
Olivier Dulac about 6 yearsI like that one as it is made with builtins, fast, and seems quite posix... I tried on an old shell (bash 2.0.5) and it works perfectly.
-
0andriy over 5 yearsWhat about spaces inside the argument? Like ” 086 “.
-
raciasolvo over 5 years@0andriy See the second test.
-
mikeserv over 5 years
OPTIND
is good here, too. just saiyan. -
Thomas Guyot-Sionnest about 4 yearsBy far the best answer yet too many people don't use parameter expansion. This works on arrays too, incl
$@
:params=("${@##*[!0-9]*}")
-- Keep all positional arguments, but only use numbers - anything else will be converted to null string which conveniently evaluates to 0 in arithmetic evaluations (my use case - function parameter is a list of integers, unset or null should default to 0 but caller sets variable name when unset). -
Thomas Guyot-Sionnest about 4 yearsBy far the best answer yet too many people don't use parameter expansion. This works on arrays too, incl $@: params=("${@##*[!0-9]*}") -- Keep all positional arguments, but only use numbers - anything else will be converted to null string which conveniently evaluates to 0 in arithmetic evaluations (my use case - function parameter is a list of integers, unset or null should default to 0 but caller sets variable name when unset).
-
Stéphane Chazelas over 3 yearsThat's not only wrong, but also a command injection vulnerability in bash and a few other shells. Try for instance with
X='x -o -v xx[$(reboot)1] -o 1'
in bash (gives true and reboots). -
Serge Stroobandt about 2 years
if [[ $scale =~ [^0-9] ]]
is less convoluted. Doing so, puts the negation in the regular expression instead of the test condition. See below. -
Admin about 2 yearsOf course, a negative sign breaks the idea.
-
Admin about 2 yearsA POSIX solution might be similar to See below.