helpermethod
helpermethod

Reputation: 62185

How can I test if a variable is *not* a positive integer?

To test whether a variable is e.g. a number greater than 0, you would write:

((i > 0))

But how would I test if the variable is not a number greater than 0?

EDIT

Sorry for the typo, meant not a number greater than 0.

EDIT 2

Sry for the poor question. The value of the variable is passed as a commandline argument, so it may be a number or not. This also needs to be checked.

Upvotes: 7

Views: 34351

Answers (5)

Op De Cirkel
Op De Cirkel

Reputation: 29473

For checking on not being number, you have to test with regex. I have used -5 instead 0 just to demonstrate more general case (My assumption is that you use integers):

#!/bin/bash

A=$1

if [[ $A =~ ^[\-0-9]+$ ]] && (( A > -5)); then
  echo "A is number and is greater then -5"
else
  echo "A is not a number or is <= -5"
fi

If you want to test for non-integers, you have to clarify in your question what is considered number.

Upvotes: 11

Todd A. Jacobs
Todd A. Jacobs

Reputation: 84353

Comparisons

This is clearly covered in the Bash manual sections on Shell Arithmetic and Bash Conditional Expressions.

# Shell arithmetic
$ (( -1 <= 0 )); echo $?
0

# Conditional expression
$ [[ -1 -le 0 ]]; echo $?
0

# Negated conditional. Confusing, but possible.
[[ ! -1 -gt 0 ]]; echo $?
0

Simple, right?

Validation

However, if you are trying to test whether or not the number is actually an integer before performing the comparsion, then you can use a compound expression like this to validate and compare a variable named int:

[[ "$int" =~ ^[-+]?([1-9][[:digit:]]*|0)$ && "$int" -le 0 ]]

Note that the comparison determines whether the validated integer is "less than or equal to zero," rather than negating the assertion that it is a positive integer. The entire expression will thus return true (e.g. an exit status of zero) only if the regular expression validates as a (possibly signed) integer and if the integer is a signed negative integer.

There are certainly other ways to construct this expression, but this is a fairly readable (if rather Bash-specific) solution.

Related Links

Upvotes: 5

Dennis Williamson
Dennis Williamson

Reputation: 360105

Simple regexes can allow non-numbers such as "11--22--99" (although they do evaluate mathematically inside the (())).

The following regex only allows 0 or negative integers without leading zeros and rejects negative zero.

for a in 0 -0 00 -1 -01 1 1-1 --1
do
    if [[ $a =~ ^(-[1-9][0-9]*|0)$ ]]
    then
        echo "[+] $a passes"
    else
        echo "[X] $a doesn't"
    fi
done

Output:

[+] 0 passes
[X] -0 doesn't
[X] 00 doesn't
[+] -1 passes
[X] -01 doesn't
[X] 1 doesn't
[X] 1-1 doesn't
[X] --1 doesn't

At this point, you don't really need to add a test for ((a <= 0)) although you could test whether it was less than or equal to some smaller number.

Edit:

You could put the integer validation test in a function and do the comparison separately for readability like this:

isint () {
    [[ $1 =~ ^(-?[1-9][0-9]*|0)$ ]] # use [+-]? instead of -? to allow "+"
}

if isint "$var" && ((var <= 0))
then
    echo "validated and compared: $var"
else
    echo "non-integer or out of range: $var"
fi

Upvotes: 3

William Pursell
William Pursell

Reputation: 212248

Yes, I realize this question is tagged bash, but there is no reason not to do this is a portable manner:

if ! test "$i" -gt 0 2> /dev/null ; then
   echo $i is not a positive integer
fi

Upvotes: 4

Daniel Kamil Kozar
Daniel Kamil Kozar

Reputation: 19286

i=15
if [[ ! $i -gt 10 ]]; then
        echo "lalala"
fi

Upvotes: 13

Related Questions