What would be the best way to check whether $1 is an integer in /bin/dash ?
In bash, I could do:
[[ $1 =~ ^([0-9]+)$ ]]
But that does not seem to be POSIX compliant and dash does not support that
What would be the best way to check whether $1 is an integer in /bin/dash ?
In bash, I could do:
[[ $1 =~ ^([0-9]+)$ ]]
But that does not seem to be POSIX compliant and dash does not support that
The following detect integers, positive or negative, and work under dash and are POSIX:
echo "$1" | grep -Eq '^[+-]?[0-9]+$' && echo "It's an integer"
case "${1#[+-]}" in
''|*[!0-9]*)
echo "Not an integer" ;;
*)
echo "Integer" ;;
esac
Or, with a little use of the : (nop) command:
! case ${1#[+-]} in *[!0-9]*) :;; ?*) ! :;; esac && echo Integer
Whether dash, bash, ksh, zsh, POSIX sh, or posh ("a reimplementation of the Bourne shell" sh) ; the case construct is the most widely available and reliable:
case $1 in (*[!0-9]*|"") false ;; (*) true ;; esac
You can use the -eq test on the string, with itself:
$ dash -c 'a="a"; if [ "$a" -eq "$a" ] ; then echo number; else echo not a number; fi'
dash: 1: [: Illegal number: a
not a number
$ dash -c 'a="0xa"; if [ "$a" -eq "$a" ] ; then echo number; else echo not a number; fi'
dash: 1: [: Illegal number: 0xa
not a number
$ dash -c 'a="-1"; if [ "$a" -eq "$a" ] ; then echo number; else echo not a number; fi'
number
If the error message is a problem, redirect error output to /dev/null:
$ dash -c 'a="0xa"; [ "$a" -eq "$a" ] 2>/dev/null|| echo no'
no
In POSIX system, you can use expr:
$ a=a
$ expr "$a" - 0 >/dev/null 2>&1
$ [ "$?" -lt 2 ] && echo Integer || echo Not Integer
Try using it as an arithmetic expansion, and see if it works. Actually, you need to be a bit stricter than that, because arithmetic expansions would ignore leading and trailing spaces, for instance. So do an arithmetic expansion, and make sure that the expanded result matches the original variable exactly.
check_if_number()
{
if [ "$1" = "$((${1}))" ] 2>/dev/null; then
echo "Number!"
else
echo "not a number"
fi
}
This would also accept negative numbers - if you really mean to exclude them, add an extra check for $((${1} >= 0)).
Perhaps with expr?
if expr match "$1" '^\([0-9]\+\)$' > /dev/null; then
echo "integer"
else
echo "non-integer"
fi
Here's a simple function using the same method as muru's answer:
IsInteger() # usage: IsInteger string
{ # returns: flag
[ "$1" -eq "$1" ] 2> /dev/null
}
Example:
p= n=2a3; IsInteger $n || p="n't" ; printf "'%s' is%s an integer\n" "$n" "$p"
p= n=23; IsInteger $n || p="n't" ; printf "'%s' is%s an integer\n" "$n" "$p"
Output:
'2a3' isn't an integer
'23' is an integer