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
Share:
205,829

Related videos on Youtube

lonewarrior556
Author by

lonewarrior556

Updated on September 18, 2022

Comments

  • lonewarrior556
    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
    lonewarrior556 almost 10 years
    that checks if its any number, not just integers
  • cuonglm
    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
    lonewarrior556 almost 10 years
    stackoverflow.com/questions/806906/… had the quotes backwards
  • Wildcard
    Wildcard over 7 years
    Good idea but a bit noisy. I would rather not have to redirect errors to dev null.
  • Olivier Dulac
    Olivier Dulac about 6 years
    I 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
    0andriy over 5 years
    What about spaces inside the argument? Like ” 086 “.
  • raciasolvo
    raciasolvo over 5 years
    @0andriy See the second test.
  • mikeserv
    mikeserv over 5 years
    OPTIND is good here, too. just saiyan.
  • Thomas Guyot-Sionnest
    Thomas Guyot-Sionnest about 4 years
    By 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
    Thomas Guyot-Sionnest about 4 years
    By 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
    Stéphane Chazelas over 3 years
    That'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
    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
    Admin about 2 years
    Of course, a negative sign breaks the idea.
  • Admin
    Admin about 2 years
    A POSIX solution might be similar to See below.