我只是不知道如何确保传递给脚本的参数是否为数字。

我只想这样做:

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

有什么帮助吗?


当前回答

我会这样做:

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

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

其他回答

老问题,但我只是想坚持我的解决方案。这一个不需要任何奇怪的外壳技巧,也不需要依赖于永远不存在的东西。

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

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

我尝试了超锯片的配方,因为它对我来说似乎是最实用的,但没能奏效。最后,我设计了另一种方法,与其他参数替换方法一样,这次使用正则表达式替换:

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

它删除$var中的每一个:digit:class字符,并检查是否剩下一个空字符串,这意味着原始字符串只有数字。

我喜欢这款车的地方是它的占地面积小,灵活性强。在这种形式中,它只适用于非分隔的、以10为基数的整数,当然您可以使用模式匹配来满足其他需要。

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

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

根据手册页,这很符合我的要求

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

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

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

在这里用一个正则表达式来测试整个部分和小数部分,并用点分隔。

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

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

我使用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有完全相同的行为。将零添加到非数字会得到零,它也会返回值零。也许你可以把bc和expr结合起来。使用bc将零添加到$number。如果答案为0,则尝试expr验证$number不为零。