How do I check to see if a variable is a number, or contains a number, in UNIX shell?
-
1The title asks if a variable is a number, the description asks if it contains a number. Which do you want? Also, when you say number d o you mean integer or should it handle decimals?gpojd– gpojd2008-11-21 19:35:19 +00:00Commented Nov 21, 2008 at 19:35
-
Do you consider 3.1415 a number?Jens– Jens2014-05-15 09:28:59 +00:00Commented May 15, 2014 at 9:28
14 Answers
if echo $var | egrep -q '^[0-9]+$'; then
# $var is a number
else
# $var is not a number
fi
5 Comments
echo $var | egrep -q '^-*[[:digit:]]+$' && echo is num || echo not num (only for base 10, of course). That even works for excessively negated but legit numbers like ----234.Shell variables have no type, so the simplest way is to use the return type test command:
if [ $var -eq $var 2> /dev/null ]; then ...
(Or else parse it with a regexp)
3 Comments
if [ -n "$var" -a $var -eq $var 2> /dev/null ]; then echo is num; else echo not a num; fiecho $((--234 * 2))).sh I tested it with.No forks, no pipes. Pure POSIX shell:
case $var in
(*[!0-9]*|'') echo not a number;;
(*) echo a number;;
esac
(Assumes number := a string of digits). If you want to allow signed numbers with a single leading - or + as well, strip the optional sign like this:
case ${var#[-+]} in
(*[!0-9]*|'') echo not a number;;
(*) echo a number;;
esac
6 Comments
sh -c 'var=--123; echo $(($var))') handle that. But freebsd >= 10 does not.In either ksh93 or bash with the extglob option enabled:
if [[ $var == +([0-9]) ]]; then ...
4 Comments
if [[ $var == +(-*[[:digit:]]) ]]; then echo is num; else echo not num; fi. Nice that this handles empty or unset var as well as multi-word var (e.g., 'brown cow'). Use [:xdigit:] character class for base 16 nums. Note: locale independent character classes (e.g., [:digit:]) don't seem to work with ksh.== operator is not symmetric in what it accepts on each side.Here's a version using only the features available in a bare-bones shell (ie it'd work in sh), and with one less process than using grep:
if expr "$var" : '[0-9][0-9]*$'>/dev/null; then
echo yes
else
echo no
fi
This checks that the $var represents only an integer; adjust the regexp to taste, and note that the expr regexp argument is implicitly anchored at the beginning.
5 Comments
expr "$var" : '-*[0-9][0-9]*$' && echo num || echo not numsh I tested it with :)'-\?[1-9][0-9]*$' or '-\?[0-9]\+$' depending on if you want to allow leading zeros or not and negative numbers or notI'm kind of newbee on shell programming so I try to find out most easy and readable It will just check the var is greater or same as 0 I think it's nice way to choose parameters... may be not what ever... :
if [ $var -ge 0 2>/dev/null ] ; then ...
1 Comment
This can be checked using regular expression.
###
echo $var|egrep '^[0-9]+$'
if [ $? -eq 0 ]; then
echo "$var is a number"
else
echo "$var is not a number"
fi
1 Comment
INTEGER
if echo "$var" | egrep -q '^\-?[0-9]+$'; then
echo "$var is an integer"
else
echo "$var is not an integer"
fi
tests (with var=2 etc.):
2 is an integer
-2 is an integer
2.5 is not an integer
2b is not an integer
NUMBER
if echo "$var" | egrep -q '^\-?[0-9]*\.?[0-9]+$'; then
echo "$var is a number"
else
echo "$var is not a number"
fi
tests (with var=2 etc.):
2 is a number
-2 is a number
-2.6 is a number
-2.c6 is not a number
2. is not a number
2.0 is a number
1 Comment
if echo $var | egrep -q '^[0-9]+$'
Actually this does not work if var is multiline.
ie
var="123
qwer"
Especially if var comes from a file :
var=`cat var.txt`
This is the simplest :
if [ "$var" -eq "$var" ] 2> /dev/null
then echo yes
else echo no
fi
1 Comment
-n "$var" to catch empty/unset var). See comments there. Good point on potential false positives for the multiline issue.Here is the test without any regular expressions (tcsh code):
Create a file checknumber:
#! /usr/bin/env tcshif ( "$*" == "0" ) then
exit 0 # number
else
((echo "$*" | bc) > /tmp/tmp.txt) >& /dev/null
set tmp = `cat /tmp/tmp.txt`
rm -f /tmp/tmp/txt
if ( "$tmp" == "" || $tmp == 0 ) then
exit 1 # not a number
else
exit 0 # number
endif
endif
and run
chmod +x checknumber
Use
checknumber -3.45
and you'll got the result as errorlevel ($?).
You can optimise it easily.
1 Comment
( test ! -z "$num" && test "$num" -eq "$num" 2> /dev/null ) && {
# $num is a number
}
2 Comments
-z check really necessary though? test "" -eq "" 2>/dev/null does what I expect here (old Bash 3.2 on standard macOS). Regardless, the parentheses seem superfluous (and cost you an unnecessary subshell).You can do that with simple test command.
$ test ab -eq 1 >/dev/null 2>&1
$ echo $?
2
$ test 21 -eq 1 >/dev/null 2>&1
$ echo $?
1
$ test 1 -eq 1 >/dev/null 2>&1
$ echo $?
0
So if the exit status is either 0 or 1 then it is a integer , but if the exis status is 2 then it is not a number.
1 Comment
a=123
if [ `echo $a | tr -d [:digit:] | wc -w` -eq 0 ]
then
echo numeric
else
echo ng
fi
numeric
a=12s3
if [ `echo $a | tr -d [:digit:] | wc -w` -eq 0 ]
then
echo numeric
else
echo ng
fi
ng
4 Comments
tr -d - in the pipeline I think.Taking the value from Command line and showing THE INPUT IS DECIMAL/NON-DECIMAL and NUMBER or not:
NUMBER=$1
IsDecimal=`echo "$NUMBER" | grep "\."`
if [ -n "$IsDecimal" ]
then
echo "$NUMBER is Decimal"
var1=`echo "$NUMBER" | cut -d"." -f1`
var2=`echo "$NUMBER" | cut -d"." -f2`
Digit1=`echo "$var1" | egrep '^-[0-9]+$'`
Digit2=`echo "$var1" | egrep '^[0-9]+$'`
Digit3=`echo "$var2" | egrep '^[0-9]+$'`
if [ -n "$Digit1" ] && [ -n "$Digit3" ]
then
echo "$NUMBER is a number"
elif [ -n "$Digit2" ] && [ -n "$Digit3" ]
then
echo "$NUMBER is a number"
else
echo "$NUMBER is not a number"
fi
else
echo "$NUMBER is not Decimal"
Digit1=`echo "$NUMBER" | egrep '^-[0-9]+$'`
Digit2=`echo "$NUMBER" | egrep '^[0-9]+$'`
if [ -n "$Digit1" ] || [ -n "$Digit2" ]; then
echo "$NUMBER is a number"
else
echo "$NUMBER is not a number"
fi
fi