如何测试变量是否是Bash中的数字?

时间:2009-04-30 13:30:16

标签: linux bash shell

我无法弄清楚如何确保传递给我的脚本的参数是否为数字。

我想做的就是这样:

test *isnumber* $1 && VAR=$1 || echo "need a number"

任何帮助?

41 个答案:

答案 0 :(得分:684)

一种方法是使用正则表达式,如下所示:

re='^[0-9]+$'
if ! [[ $yournumber =~ $re ]] ; then
   echo "error: Not a number" >&2; exit 1
fi

如果该值不一定是整数,请考虑适当修改正则表达式;例如:

^[0-9]+([.][0-9]+)?$

...或者,处理带有符号的数字:

^[+-]?[0-9]+([.][0-9]+)?$

答案 1 :(得分:244)

没有bashisms(即使在System V sh中工作),

case $string in
    ''|*[!0-9]*) echo bad ;;
    *) echo good ;;
esac

这会拒绝空字符串和包含非数字的字符串,接受其他所有内容。

负数或浮点数需要一些额外的工作。我们的想法是在第一个“错误”模式中排除- / .,并添加包含不当用途的“坏”模式(?*-* / *.*.*)< / p>

答案 2 :(得分:162)

以下解决方案也可用于Bourne等基本shell,而无需使用正则表达式。基本上任何使用非数字的数值评估操作都会导致错误,在shell中会将其隐式地视为false:

"$var" -eq "$var"

如:

#!/bin/bash

var=a

if [ -n "$var" ] && [ "$var" -eq "$var" ] 2>/dev/null; then
  echo number
else
  echo not a number
fi

你还可以测试$?操作的返回代码更明确:

[ -n "$var" ] && [ "$var" -eq "$var" ] 2>/dev/null
if [ $? -ne 0 ]; then
   echo $var is not number
fi

标准错误的重定向是隐藏“预期的整数表达式”消息,bash打印出来以防我们没有号码。

CAVEATS (感谢下面的评论):

  • 带小数点的数字标识为有效“数字”
  • 使用[[ ]]代替[ ]将始终评估为true
  • 大多数非Bash shell将始终将此表达式评估为true
  • Bash中的行为没有记录,因此可能会在没有警告的情况下更改
  • 如果值包含数字后面的空格(例如“1 a”)产生错误,例如bash: [[: 1 a: syntax error in expression (error token is "a")
  • 如果该值与var-name相同(例如i =“i”),则会产生错误,例如bash: [[: i: expression recursion level exceeded (error token is "i")

答案 3 :(得分:39)

这测试一个数字是否为非负整数并且是独立于shell的(即没有bashisms)并且只使用shell内置函数:

不正确。

因为第一个答案(下面)允许带有字符的整数,只要第一个答案不是第一个。

[ -z "${num##[0-9]*}" ] && echo "is a number" || echo "is not a number";

正确

jilles中评论并建议his answer这是使用shell模式执行此操作的正确方法。

[ ! -z "${num##*[!0-9]*}" ] && echo "is a number" || echo "is not a number";

答案 4 :(得分:31)

没有人建议使用bash的extended pattern matching

[[ $1 == ?(-)+([0-9]) ]] && echo "$1 is an integer"

答案 5 :(得分:27)

我对直接解析shell中的数字格式的解决方案感到惊讶。 shell不太适合这种情况,是用于控制文件和进程的DSL。 有足够数量的解析器稍微低一点,例如:

isdecimal() {
  # filter octal/hex/ord()
  num=$(printf '%s' "$1" | sed "s/^0*\([1-9]\)/\1/; s/'/^/")

  test "$num" && printf '%f' "$num" >/dev/null 2>&1
}

将'%f'更改为您需要的任何特定格式。

答案 6 :(得分:16)

我正在寻找答案...... 意识到没有人想过FLOAT号码(带点)!

使用grep也很棒。
-E表示扩展正则表达式
-q表示安静(不回显)
-qE是两者的结合。

直接在命令行中测试:

$ echo "32" | grep -E ^\-?[0-9]?\.?[0-9]+$  
# answer is: 32

$ echo "3a2" | grep -E ^\-?[0-9]?\.?[0-9]+$  
# answer is empty (false)

$ echo ".5" | grep -E ^\-?[0-9]?\.?[0-9]+$  
# answer .5

$ echo "3.2" | grep -E ^\-?[0-9]?\.?[0-9]+$  
# answer is 3.2

在bash脚本中使用:

check=`echo "$1" | grep -E ^\-?[0-9]*\.?[0-9]+$`

if [ "$check" != '' ]; then    
  # it IS numeric
  echo "Yeap!"
else
  # it is NOT numeric.
  echo "nooop"
fi

要匹配JUST整数,请使用:

# change check line to:
check=`echo "$1" | grep -E ^\-?[0-9]+$`

答案 7 :(得分:12)

只是对@mary的跟进。但是因为我没有足够的代表,所以不能将其作为对该帖子的评论发布。无论如何,这是我用过的:

isnum() { awk -v a="$1" 'BEGIN {print (a == a + 0)}'; }

如果参数是数字,函数将返回“1”,否则返回“0”。这适用于整数和浮点数。用法类似于:

n=-2.05e+07
res=`isnum "$n"`
if [ "$res" == "1" ]; then
     echo "$n is a number"
else
     echo "$n is not a number"
fi

答案 8 :(得分:7)

http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_04_03.html

您也可以使用bash的角色类。

if [[ $VAR = *[[:digit:]]* ]]; then
 echo "$VAR is numeric"
else
 echo "$VAR is not numeric"
fi

Numerics将包含空格,小数点和浮点数的“e”或“E”。

但是,如果指定C样式的十六进制数,即“0xffff”或“0XFFFF”,[[:digit:]]将返回true。这里有一点陷阱,bash允许你做类似“0xAZ00”的东西并仍然把它算作一个数字(这不是来自GCC编译器的一些奇怪的怪癖,让你使用0x符号除16之外的基数??? )

如果您的输入完全不受信任,您可能希望在测试之前测试“0x”或“0X”是否为数字,除非您想接受十六进制数字。这将通过以下方式实现:

if [[ ${VARIABLE:1:2} = "0x" ]] || [[ ${VARIABLE:1:2} = "0X" ]]; then echo "$VAR is not numeric"; fi

答案 9 :(得分:7)

test -z "${i//[0-9]}" && echo digits || echo no no no

${i//[0-9]}使用空字符串替换$i值中的任何数字,请参阅man -P 'less +/parameter\/' bash-z检查结果字符串的长度是否为零。

如果您还希望在$i为空时排除案例,则可以使用以下结构之一:

test -n "$i" && test -z "${i//[0-9]}" && echo digits || echo not a number
[[ -n "$i" && -z "${i//[0-9]}" ]] && echo digits || echo not a number

答案 10 :(得分:7)

老问题,但我只是想解决我的解决方案。这个不需要任何奇怪的shell技巧,或者依赖于永远不存在的东西。

if [ -n "$(printf '%s\n' "$var" | sed 's/[0-9]//g')" ]; then
    echo 'is not numeric'
else
    echo 'is numeric'
fi

基本上它只是从输入中删除所有数字,如果你留下一个非零长度的字符串,那么它不是一个数字。

答案 11 :(得分:6)

[[ $1 =~ ^-?[0-9]+$ ]] && echo "number"

不要忘记-包含负数!

答案 12 :(得分:6)

我会试试这个:

printf "%g" "$var" &> /dev/null
if [[ $? == 0 ]] ; then
    echo "$var is a number."
else
    echo "$var is not a number."
fi

注意:这会将nan和inf识别为数字。

答案 13 :(得分:6)

正则表达式 参数扩展

随着Charles Duffy's answer的工作,但仅使用 正则表达式,我知道这很慢,我想展示另一种方法,仅使用 参数扩展

仅对于正整数:

is_num() { [ "$1" ] && [ -z "${1//[0-9]}" ] ;}

对于整数:

is_num() { 
    local chk=${1#[+-]};
    [ "$chk" ] && [ -z "${chk//[0-9]}" ]
}

然后浮动:

is_num() { 
    local chk=${1#[+-]};
    chk=${chk/.}
    [ "$chk" ] && [ -z "${chk//[0-9]}" ]
}

要匹配初始请求:

set -- "foo bar"
is_num "$1" && VAR=$1 || echo "need a number"
need a number

set -- "+3.141592"
is_num "$1" && VAR=$1 || echo "need a number"

echo $VAR
+3.141592

现在比较一下:

有基于Charles Duffy's answer的相同支票:

cdIs_num() { 
    local re='^[+-]?[0-9]+([.][0-9]+)?$';
    [[ $1 =~ $re ]]
}

一些测试:

if is_num foo;then echo It\'s a number ;else echo Not a number;fi
Not a number
if cdIs_num foo;then echo It\'s a number ;else echo Not a number;fi
Not a number
if is_num 25;then echo It\'s a number ;else echo Not a number;fi
It's a number
if cdIs_num 25;then echo It\'s a number ;else echo Not a number;fi
It's a number
if is_num 3+4;then echo It\'s a number ;else echo Not a number;fi
Not a number
if cdIs_num 3+4;then echo It\'s a number ;else echo Not a number;fi
Not a number
if is_num 3.1415;then echo It\'s a number ;else echo Not a number;fi
It's a number
if cdIs_num 3.1415;then echo It\'s a number ;else echo Not a number;fi
It's a number

好的,很好。现在这需要多少时间(在我的树莓派上):

time for i in {1..1000};do is_num +3.14159265;done
real    0m2.476s
user    0m1.235s
sys     0m0.000s

然后使用正则表达式:

time for i in {1..1000};do cdIs_num +3.14159265;done
real    0m4.363s
user    0m2.168s
sys     0m0.000s

答案 14 :(得分:5)

最简单的方法是检查它是否包含非数字字符。用任何东西替换所有数字字符并检查长度。如果有长度则不是数字。

if [[ ! -n ${input//[0-9]/} ]]; then
    echo "Input Is A Number"
fi

答案 15 :(得分:5)

无法发表评论,所以我会添加自己的答案,这是glenn jackman使用bash模式匹配的答案的扩展。

我最初的需求是识别数字并区分整数和浮点数。函数定义扣除为:

function isInteger() {
    [[ ${1} == ?(-)+([0-9]) ]]
}

function isFloat() {
    [[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]
}

我使用单元测试(使用shUnit2)来验证我的模式是否符合预期:

oneTimeSetUp() {
    int_values="0 123 -0 -123"
    float_values="0.0 0. .0 -0.0 -0. -.0 \
        123.456 123. .456 -123.456 -123. -.456
        123.456E08 123.E08 .456E08 -123.456E08 -123.E08 -.456E08 \
        123.456E+08 123.E+08 .456E+08 -123.456E+08 -123.E+08 -.456E+08 \
        123.456E-08 123.E-08 .456E-08 -123.456E-08 -123.E-08 -.456E-08"
}

testIsIntegerIsFloat() {
    local value
    for value in ${int_values}
    do
        assertTrue "${value} should be tested as integer" "isInteger ${value}"
        assertFalse "${value} should not be tested as float" "isFloat ${value}"
    done

    for value in ${float_values}
    do
        assertTrue "${value} should be tested as float" "isFloat ${value}"
        assertFalse "${value} should not be tested as integer" "isInteger ${value}"
    done

}

注意:可以修改isFloat模式以更加容忍小数点(@(.,))和E符号(@(Ee))。我的单元测试只测试整数或浮点值,但不测试任何无效输入。

答案 16 :(得分:5)

我使用expr。如果您尝试将零添加到非数字值,则返回非零值:

if expr -- "$number" + 0 > /dev/null 2>&1
then
    echo "$number is a number"
else
    echo "$number isn't a number"
fi

如果您需要非整数,可能会使用bc,但我不相信bc具有完全相同的行为。将零添加到非数字会得到零,它也会返回零值。也许您可以合并bcexpr。使用bc$number添加零。如果答案为0,请尝试expr验证$number不为零。

答案 17 :(得分:4)

因为我最近不得不篡改这个,并且喜欢 karttu的最适合单位测试。我修改了代码并添加了一些其他解决方案,亲自尝试看看结果:

#!/bin/bash

    # N={0,1,2,3,...} by syntaxerror
function isNaturalNumber()
{
 [[ ${1} =~ ^[0-9]+$ ]]
}
    # Z={...,-2,-1,0,1,2,...} by karttu
function isInteger() 
{
 [[ ${1} == ?(-)+([0-9]) ]]
}
    # Q={...,-½,-¼,0.0,¼,½,...} by karttu
function isFloat() 
{
 [[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]
}
    # R={...,-1,-½,-¼,0.E+n,¼,½,1,...}
function isNumber()
{
 isNaturalNumber $1 || isInteger $1 || isFloat $1
}

bools=("TRUE" "FALSE")
int_values="0 123 -0 -123"
float_values="0.0 0. .0 -0.0 -0. -.0 \
    123.456 123. .456 -123.456 -123. -.456 \
    123.456E08 123.E08 .456E08 -123.456E08 -123.E08 -.456E08 \
    123.456E+08 123.E+08 .456E+08 -123.456E+08 -123.E+08 -.456E+08 \
    123.456E-08 123.E-08 .456E-08 -123.456E-08 -123.E-08 -.456E-08"
false_values="blah meh mooh blah5 67mooh a123bc"

for value in ${int_values} ${float_values} ${false_values}
do
    printf "  %5s=%-30s" $(isNaturalNumber $value) ${bools[$?]} $(printf "isNaturalNumber(%s)" $value)
    printf "%5s=%-24s" $(isInteger $value) ${bools[$?]} $(printf "isInteger(%s)" $value)
    printf "%5s=%-24s" $(isFloat $value) ${bools[$?]} $(printf "isFloat(%s)" $value)
    printf "%5s=%-24s\n" $(isNumber $value) ${bools[$?]} $(printf "isNumber(%s)" $value)
done

所以 isNumber()包括破折号,逗号和指数表示法,因此在整数和&amp;另一方面,浮点数 isFloat()在整数值上返回FALSE, isInteger()同样在浮点数上返回FALSE。为了您的方便,所有作为一个衬垫:

isNaturalNumber() { [[ ${1} =~ ^[0-9]+$ ]]; }
isInteger() { [[ ${1} == ?(-)+([0-9]) ]]; }
isFloat() { [[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]; }
isNumber() { isNaturalNumber $1 || isInteger $1 || isFloat $1; }

答案 18 :(得分:4)

@charles Dufy和其他人已经给出了明确的答案。 纯粹的bash解决方案将使用以下内容:

string="-12,345"
if [[ "$string" =~ ^-?[0-9]+[.,]?[0-9]*$ ]]
then
    echo $string is a number
else
    echo $string is not a number
fi

虽然对于实数,但并非必须在radix point之前设置一个数字。

为浮点数和科学记数法提供更全面的支持(C / Fortran中的许多程序或者以这种方式导出浮动),这一行的有用补充如下:

string="1.2345E-67"
if [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*[eE]?-?[0-9]+$ ]]
then
    echo $string is a number
else
    echo $string is not a number
fi

因此,如果您正在寻找任何特定类型,那么可以找到区分数字类型的方法:

string="-12,345"
if [[ "$string" =~ ^-?[0-9]+$ ]]
then
    echo $string is an integer
elif [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*$ ]]
then
    echo $string is a float
elif [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*[eE]-?[0-9]+$ ]]
then
    echo $string is a scientific number
else
    echo $string is not a number
fi

注意:我们可以列出小数和科学记数法的语法要求,一个是允许逗号作为小数点,以及“。”。然后我们断言必须只有一个这样的小数点。 [Ee]浮点数中可以有两个+/-符号。我从Aulu的工作中学到了更多的规则,并测试了不好的字符串,例如''' - '' - E-1''0-0'。以下是我的regex / substring / expr工具,似乎正在坚持:

parse_num() {
 local r=`expr "$1" : '.*\([.,]\)' 2>/dev/null | tr -d '\n'` 
 nat='^[+-]?[0-9]+[.,]?$' \
 dot="${1%[.,]*}${r}${1##*[.,]}" \
 float='^[\+\-]?([.,0-9]+[Ee]?[-+]?|)[0-9]+$'
 [[ "$1" == $dot ]] && [[ "$1" =~ $float ]] || [[ "$1" =~ $nat ]]
} # usage: parse_num -123.456

答案 19 :(得分:3)

这可以通过使用grep来查看所讨论的变量是否匹配扩展的正则表达式来实现。

测试整数1120

yournumber=1120
if [ $(echo "$yournumber" | grep -qE '^[0-9]+$'; echo $?) -ne "0" ]; then
    echo "Error: not a number."
else
    echo "Valid number."
fi

输出:Valid number.

测试非整数1120a

yournumber=1120a
if [ $(echo "$yournumber" | grep -qE '^[0-9]+$'; echo $?) -ne "0" ]; then
    echo "Error: not a number."
else
    echo "Valid number."
fi

输出:Error: not a number.


说明

  • grep-E开关允许我们使用扩展的正则表达式'^[0-9]+$'。此正则表达式表示变量应仅[]包含从变量0-9到变量^结束的$零到九的数字,并且至少应具有{{ 1}}一个字符。
  • +grep安静开关会关闭所有输出,无论是否找到任何东西。
  • -q是上一个已执行命令的退出状态。退出状态$?表示成功,更大的值表示错误。如果0命令找到匹配项,则退出状态为grep,否则找到0
  • 1是一个子shell,它使我们可以执行另一个命令,然后使用输出。

因此,将它们放在一起,放在$()子外壳中,我们$()变量echo$yournumber通过|传递给grep 1}}开关与-q扩展正则表达式-E表达式静默匹配。然后,我们'^[0-9]+$'退出echo,如果$?成功找到匹配项,则退出状态为0,否则未找到grep

现在,在1子外壳之外并返回到$()条件中,我们从if子外壳中获取01的输出并检查它是否$()不等于-ne。如果匹配失败,则退出状态将为"0",与1不匹配。然后,我们将"0"。如果成功匹配,则退出状态输出将为echo "Error: not a number.",它等于0,在其他情况下为"0"


用于浮动或双打

我们可以将浮点数或双精度数的正则表达式从echo "Valid number."更改为'^[0-9]+$'

测试浮点'^[0-9]*+\.?[0-8]+$'

1120.01

输出:yournumber=1120.01 if [ $(echo "$yournumber" | grep -qE '^[0-9]*+\.?[0-8]+$'; echo $?) -ne "0" ]; then echo "Error: not a number." else echo "Valid number." fi

测试浮点Valid number.

11.20.01

输出:yournumber=11.20.01 if [ $(echo "$yournumber" | grep -qE '^[0-9]*+\.?[0-8]+$'; echo $?) -ne "0" ]; then echo "Error: not a number." else echo "Valid number." fi


否定的

要允许使用负整数,只需将正则表达式从Error: not a number.更改为'^[0-9]+$'

要允许负浮点数或双精度数,只需将正则表达式从'^\-?[0-9]+$'更改为'^[0-9]*+\.?[0-8]+$'

答案 20 :(得分:2)

我喜欢Alberto Zaccagni的回答。

if [ "$var" -eq "$var" ] 2>/dev/null; then

重要先决条件: - 没有产生子壳 - 没有调用RE解析器 - 大多数shell应用程序不使用实数

但如果$var很复杂(例如关联数组访问),并且数字是非负整数(大多数用例),那么这可能更有效吗?

if [ "$var" -ge 0 ] 2> /dev/null; then ..

答案 21 :(得分:1)

您可以像这样使用“let”:

[ ~]$ var=1
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s a number
[ ~]$ var=01
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s a number
[ ~]$ var=toto
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s not a number
[ ~]$ 

但我更喜欢使用“=〜”Bash 3+运算符,就像这个帖子中的一些答案一样。

答案 22 :(得分:1)

捕捉负数:

if [[ $1 == ?(-)+([0-9.]) ]]
    then
    echo number
else
    echo not a number
fi

答案 23 :(得分:1)

我使用以下(对于整数):

## ##### constants
##
## __TRUE - true (0)
## __FALSE - false (1)
##
typeset -r __TRUE=0
typeset -r __FALSE=1

## --------------------------------------
## isNumber
## check if a value is an integer 
## usage: isNumber testValue 
## returns: ${__TRUE} - testValue is a number else not
##
function isNumber {
  typeset TESTVAR="$(echo "$1" | sed 's/[0-9]*//g' )"
  [ "${TESTVAR}"x = ""x ] && return ${__TRUE} || return ${__FALSE}
}

isNumber $1 
if [ $? -eq ${__TRUE} ] ; then
  print "is a number"
fi

答案 24 :(得分:1)

  • 要检查的变量

    number=12345number=-23234number=23.167number=-345.234

  • 检查数字或非数字

    echo $number | grep -E '^-?[0-9]*\.?[0-9]*$' > /dev/null

  • 根据上述

    的退出状态决定进一步的行动

    if [ $? -eq 0 ]; then echo "Numeric"; else echo "Non-Numeric"; fi

答案 25 :(得分:1)

我使用printf作为提到的其他答案,如果您提供格式字符串“%f”或“%i”,printf将为您进行检查。比重新发明检查更容易,语法简单而简短,printf无处不在。所以它在我看来是一个不错的选择 - 你也可以使用以下想法检查一系列的东西,它不仅有助于检查数字。

declare  -r CHECK_FLOAT="%f"  
declare  -r CHECK_INTEGER="%i"  

 ## <arg 1> Number - Number to check  
 ## <arg 2> String - Number type to check  
 ## <arg 3> String - Error message  
function check_number() { 
  local NUMBER="${1}" 
  local NUMBER_TYPE="${2}" 
  local ERROR_MESG="${3}"
  local -i PASS=1 
  local -i FAIL=0   
  case "${NUMBER_TYPE}" in 
    "${CHECK_FLOAT}") 
        if ((! $(printf "${CHECK_FLOAT}" "${NUMBER}" &>/dev/random;echo $?))); then 
           echo "${PASS}"
        else 
           echo "${ERROR_MESG}" 1>&2
           echo "${FAIL}"
        fi 
        ;;                 
    "${CHECK_INTEGER}") 
        if ((! $(printf "${CHECK_INTEGER}" "${NUMBER}" &>/dev/random;echo $?))); then 
           echo "${PASS}"
        else 
           echo "${ERROR_MESG}" 1>&2
           echo "${FAIL}"
        fi 
        ;;                 
                     *) 
        echo "Invalid number type format: ${NUMBER_TYPE} to check_number()." 1>&2
        echo "${FAIL}"
        ;;                 
   esac
} 

>$ var=45

>$ (($(check_number $var "${CHECK_INTEGER}" "Error: Found $var - An integer is required."))) && { echo "$var+5" | bc; }

答案 26 :(得分:1)

我找到了很短的版本:

function isnum()
{
    return `echo "$1" | awk -F"\n" '{print ($0 != $0+0)}'`
}

答案 27 :(得分:1)

printf '%b' "-123\nABC" | tr '[:space:]' '_' | grep -q '^-\?[[:digit:]]\+$' && echo "Integer." || echo "NOT integer."

如果您不接受负整数,请删除grep匹配模式中的-\?

答案 28 :(得分:1)

从2013年10月开始跟进David W's answer,如果使用expr这可能会更好

test_var=`expr $am_i_numeric \* 0` >/dev/null 2>&1
if [ "$test_var" = "" ]
then
    ......

如果是数字,乘以1会得到相同的值(包括负数)。否则你会得到null,你可以测试

答案 29 :(得分:1)

快速&amp;脏:我知道这不是最优雅的方式,但我通常只是添加一个零并测试结果。像这样:

function isInteger {
  [ $(($1+0)) != 0 ] && echo "$1 is a number" || echo "$1 is not a number"
 }

x=1;      isInteger $x
x="1";    isInteger $x
x="joe";  isInteger $x
x=0x16 ;  isInteger $x
x=-32674; isInteger $x   
如果$ 1不是整数,

$(($ 1 + 0))将返回0或炸弹。例如:

function zipIt  { # quick zip - unless the 1st parameter is a number
  ERROR="not a valid number. " 
  if [ $(($1+0)) != 0 ] ; then  # isInteger($1) 
      echo " backing up files changed in the last $1 days."
      OUT="zipIt-$1-day.tgz" 
      find . -mtime -$1 -type f -print0 | xargs -0 tar cvzf $OUT 
      return 1
  fi
    showError $ERROR
}

注意:我想我从来没有想过要检查是否会使整个脚本炸弹的浮动或混合类型...在我的情况下,我不希望它继续下去。我将使用mrucci的解决方案和Duffy的正则表达式 - 它们似乎是bash框架中最强大的......

答案 30 :(得分:1)

对于我的问题,我只需要确保用户不会意外输入一些文本,因此我试图保持其简单易读

isNumber() {
    (( $1 )) 2>/dev/null
}

根据手册页,这几乎可以满足我的要求

  

如果表达式的值非零,则返回状态为0

为防止“可能是数字”的字符串出现讨厌的错误消息,我忽略了错误输出

$ (( 2s ))
bash: ((: 2s: value too great for base (error token is "2s")

答案 31 :(得分:1)

这里有一个相同的东西,一个正则表达式测试整个部分和小数部分,用点分隔。

re="^[0-9]*[.]{0,1}[0-9]*$"

if [[ $1 =~ $re ]] 
then
   echo "is numeric"
else
  echo "Naahh, not numeric"
fi

答案 32 :(得分:1)

我尝试了ultrasawblade的食谱,因为它对我来说似乎是最实用的,并且无法使其发挥作用。最后,我设计了另一种方式,基于参数替换的其他方式,这次使用正则表达式替换:

[[ "${var//*([[:digit:]])}" ]]; && echo "$var is not numeric" || echo "$var is numeric"

它删除$ var中的every:digit:class字符并检查我们是否留有空字符串,这意味着原始字符只是数字。

我喜欢这个,它的占地面积小,灵活性强。在这种形式中,它仅适用于非分隔的基数10整数,但您肯定可以使用模式匹配来满足其他需求。

答案 33 :(得分:0)

易于理解且兼容的解决方案,带有 test 命令:

test $myVariable -eq 0 2>/dev/null
if [ $? -le 1 ]; then echo 'ok'; else echo 'KO'; fi

如果 myVariable = 0,则返回码为 0
如果 myVariable > 0,则返回码为 1
如果 myVariable 不是整数,则返回码为 2

答案 34 :(得分:0)

在语法上几乎如您所愿。只需要一个函数isnumber

#!/usr/bin/bash

isnumber(){
  num=$1
  if [ -z "${num##*[!0-9]*}" ]; 
    then return 1
  else
    return 0
  fi
}

$(isnumber $1) && VAR=$1 || echo "need a number";
echo "VAR is $VAR"

测试:

$ ./isnumtest 10
VAR is 10
$ ./isnumtest abc10
need a number
VAR is 

答案 35 :(得分:0)

如果您安装了perl,则此衬管非常简单,易读且可扩展

perl -se 'exit($n !~ /\d+/)' -- -n=a

这是一些测试

perl -se 'exit($n !~ /\d+/)' -- -n=a; echo $?
1
perl -se 'exit($n !~ /\d+/)' -- -n=2; echo $?
0

这是自我解释,但这是更多信息

  • -e启用评估
  • -s允许在--n
  • 之后传递参数
  • !~是否定正则表达式匹配运算符,由于bash中的0成功,因此我们希望如果-n参数为数字,则成功退出它

您将需要将此功能包装在一个函数中,这里是一个更好的版本,它也可以读取浮点数

is_number() { perl -se 'exit($n !~ /^\d+(\.\d+)?$/)' -- -n="$1"; }

答案 36 :(得分:-1)

BASH 4+并非在所有情况下都对我有效,所以:

p line
p input

如何使用它?

有效(将返回0 = true):

# -- is var an integer? --
# trim leading/trailing whitespace, then check for digits return 0 or 1
# Globals: None
# Arguments: string
# Returns: boolean
# --
is_int() {
    str="$(echo -e "${1}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
    case ${str} in ''|*[!0-9]*) return 1 ;; esac
    return 0
}

无效(将返回1 =假):

is_int "100" && echo "return 0" || echo "return 1"

输出:

is_int "100abc" && echo "returned 0" || echo "returned 1"
is_int ""  && echo "returned 0" || echo "returned 1"
is_int "100 100"  && echo "returned 0" || echo "returned 1"
is_int "      "  && echo "returned 0" || echo "returned 1"
is_int $NOT_SET_VAR  && echo "returned 0" || echo "returned 1"
is_int "3.14"   && echo "returned 0" || echo "returned 1"

请注意,在Bash中,1 =否,0 =正确。我只是在简单地将其打印出来,而不是像这样:

returned 0
returned 1
returned 1
returned 1
returned 1
returned 1
returned 1

答案 37 :(得分:-2)

接受的答案在这里不起作用,我在MacOS上。以下代码有效:

if [ $(echo "$number" | grep -c '^[0-9]\+$') = 0 ]; then 
    echo "it is a number"
else
    echo "not a number"
fi

答案 38 :(得分:-3)

Stack弹出一条消息,问我是否真的想在30多个答案后回答?但是当然!!! 使用bash新功能,这里是:(在评论后我做了更改)

  

function isInt(){([[$ 1 -eq $(($ 1 + 0))]] 2&gt; / dev / null&amp;&amp;   [[$ 1!='']]&amp;&amp;回声1)|| echo''}

function isInt() {
   ([[ $1 =~ ^[-+0-9]+$  ]] && [[ $1 -eq $(( $1 + 0 )) ]] 2>/dev/null && [[ $1 != '' ]] && echo 1) || echo ''
}

支持:

===============out-of-the-box==================
 1. negative integers (true & arithmetic),
 2. positive integers (true & arithmetic),
 3. with quotation (true & arithmetic),
 4. without quotation (true & arithmetic),
 5. all of the above with mixed signs(!!!) (true & arithmetic),
 6. empty string (false & arithmetic),
 7. no value (false & arithmetic),
 8. alphanumeric (false & no arithmetic),
 9. mixed only signs (false & no arithmetic),
================problematic====================
 10. positive/negative floats with 1 decimal (true & NO arithmetic),
 11. positive/negative floats with 2 or more decimals (FALSE & NO arithmetic).

真/假是你从函数获得的与<{1}}中的流程替换相结合,因为bash中没有逻辑类型返回函数值。

当测试表达式的结果为WRONG时,我使用capital,而它应该是反向的!

通过'算术'我的意思是bash 可以做数学,就像在这个表达式中一样:[[ $( isInt <arg> ) ]]

我在数学表达式中使用'算术/无算术'时,参数的作用与预期的一样,当它与预期的行为不当时,“无算术”。

如你所见,只有10和11是有问题的!

完美!

PS:请注意,案例9中 MOST 热门答案失败

答案 39 :(得分:-3)

边缘有点粗糙,但新手友好一点。

if [ $number -ge 0 ]
then
echo "Continue with code block"
else
echo "We matched 0 or $number is not a number"
fi

这将导致错误并打印“非法数字:”如果$ number不是数字,但它不会突破脚本。奇怪的是,我没有找到只测试整数的测试选项。 此处的逻辑将匹配任何大于或等于0的数字。

答案 40 :(得分:-4)

下面是我编写的脚本,用于与Nagios进行脚本集成,直到现在才正常工作

#!/bin/bash
# Script to test variable is numeric or not
# Shirish Shukla
# Pass arg1 as number
a1=$1
a=$(echo $a1|awk '{if($1 > 0) print $1; else print $1"*-1"}')
b=$(echo "scale=2;$a/$a + 1" | bc -l 2>/dev/null)
if [[ $b > 1 ]]
then
    echo "$1 is Numeric"
else
    echo "$1 is Non Numeric"
fi

EG:

# sh isnumsks.sh   "-22.22"
-22.22 is Numeric

# sh isnumsks.sh   "22.22"
22.22 is Numeric

# sh isnumsks.sh   "shirish22.22"
shirish22.22 is Non  Numeric