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

我只想这样做:

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

有什么帮助吗?


当前回答

@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

尽管对于实数,在基数点之前不必有数字。

为了更全面地支持浮点数和科学记数法(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]浮点数中可以有两个+/-符号。我从奥卢的工作中学到了更多的规则,并测试了“”-“”-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

其他回答

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

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

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

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

跟进2013年10月David W的回答,如果使用expr,这可能会更好

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

如果是数字,则乘以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}”“错误:找到$var-需要一个整数。”))&{echo“$var+5”|bc;}

这将测试数字是否为非负整数。它是独立于外壳的(即没有bashms),只使用外壳内置:

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

此答案的先前版本提出:

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

但这是不正确的,因为它接受任何以数字开头的字符串,正如jilles所建议的那样。

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

测试整数1120:

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

输出:有效数字。

测试非整数1120a:

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

输出:错误:不是数字。


解释

grep和-E开关允许我们使用扩展正则表达式“^[0-9]+$”。此正则表达式表示变量从^开始到$结束只应[]包含0-9 0到9的数字,并且至少应有+1个字符。grep,-q quiet开关关闭任何输出,无论它是否找到任何内容。if检查grep的退出状态。退出状态0表示成功,大于0表示错误。如果grep命令找到匹配项,则其退出状态为0,如果没有找到,则为1;

因此,在if测试中,我们将所有这些放在一起,返回变量$yournumber并|将其通过管道传递给grep,grep使用-q开关与-E扩展正则表达式“^[0-9]+$”表达式匹配。如果grep成功找到匹配项,则grep的退出状态为0,如果没有找到匹配项则为1。如果匹配成功,我们将返回“有效数字”。如果匹配失败,我们将回显“错误:不是数字”。


对于浮球或双打

我们可以将正则表达式从“^[0-9]+$”更改为“^[0-10]*\”。?[0-9]+$'表示浮点或双精度。

测试浮子1120.01:

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

输出:有效数字。

测试浮子11.20.01:

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

输出:错误:不是数字。


对于否定词

要允许负整数,只需将正则表达式从“^[0-9]+$”更改为“^\-?[0-9]+$'.

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