Checking if an input number is an integer

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]+$" ]]
            echo "Sorry integers only"

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?

Asked By: lonewarrior556


Use -eq operator of test command:

read scale
if ! [ "$scale" -eq "$scale" ] 2> /dev/null
    echo "Sorry integers only"

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.
Answered By: cuonglm

Remove quotes

if ! [[ "$scale" =~ ^[0-9]+$ ]]
        echo "Sorry integers only"
Answered By: jimmij
( scale=${scale##*[!0-9]*}
: ${scale:?input must be an integer}
) || exit

That does the check and outputs your error.

Answered By: mikeserv

For unsigned integers I use:

read -r scale
[ -z "${scale//[0-9]}" ] && [ -n "$scale" ] || echo "Sorry integers only"


$ ./
$ ./
$ ./
Sorry integers only
$ ./
Sorry integers only
$ ./

Sorry integers only
Answered By: raciasolvo

As the OP seems to want only positive integers:

[ "$1" -ge 0 ] 2>/dev/null


$ is_positive_int(){ [ "$1" -ge 0 ] 2>/dev/null && echo YES || echo no; }
$ is_positive_int word
$ is_positive_int 2.1
$ is_positive_int -3
$ is_positive_int 42

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

This is because dereferencing occurs with [[:

$ word=other
$ other=3                                                                                                                                                                                  
$ [[ $word -eq 3 ]] && echo word equals other equals 3
word equals other equals 3
Answered By: Tom Hale

A POSIX and portable solution is:

read scale
if     [ -z "${scale##*[!0-9]*}" ]; 
then   echo "Sorry integers only"
Answered By: user232326

In bash, you can use the extended patterns inside [[...]]:

[[ $scale == +([[:digit:]]) ]] || echo "Sorry integers only"
# ==> no output
[[ $scale == +([[:digit:]]) ]] || echo "Sorry integers only"
# ==> Sorry integers only
Answered By: glenn jackman

For X greater than 0 I use

[ 0$X -gt 0 2>/dev/null ] && echo "is number" || echo "is string"

this gives no error if X is empty

Answered By: illulix


case $1 in
  ("" | *[!0123456789]*)
    echo >&2 Sorry, decimal integer only
    exit 1

Do not use [0-9] which often matches a lot more than [0123456789] (especially with bash globs, YMMV for bash’s [[ =~ ]] operator which uses the system regexps where [0-9] may or may not match more than 0123456789 depending on the system and locale).

More on that at what is the meaning of this shell script function

Note that you may also want to reject numbers like 08 or 09 which some tools (including bash arithmetic operators) reject as invalid octal numbers.

Answered By: Stéphane Chazelas

Less convoluted

The negation is now in the regular expression instead of the test condition.

if [[ $scale =~ [^0-9] ]]
        echo "Sorry integers only"


  • =~ binary operator where the string to the right of the operator is considered an extended regular expression and matched accordingly (as in regex(3))
  • [^0-9] matches a single character not present in the list 0-9.
Answered By: Serge Stroobandt

The following is POSIX compliant, so it will work in other shells than bash as well. Just checking -z "${scale##*[!0-9]*}" as suggested by another answer here does not take into account that strings starting with zero (except for zero itself) or empty strings are also not valid base-10 integers.

case "$scale" in *[!0123456789]*|0?*|"")
    echo "Sorry integers only";;

We need to spell out all valid digits because using a range like 0-9 matches on any character (or possibly multi-character collation element) that sorts in between 0 and 9. Thanks to @st├ęphane-chazelas for this insight. More about that here:

If negative integers are valid in your use case, you can use:

case "$scale" in *[!0123456789-]*|-|?*-*|0?*|-0|"")
    echo "Sorry integers only";;
Answered By: josch