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

我只想这样做:

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

有什么帮助吗?


当前回答

公认的答案在这里行不通,我在MacOS上。以下代码有效:

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

其他回答

现在还不能评论,所以我将添加我自己的答案,这是使用bash模式匹配对glenn jackman答案的扩展。

我最初的需要是识别数字,区分整数和浮点数。函数定义被推导为:

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))更宽容。我的单元测试只测试整数或浮点值,但不测试任何无效输入。

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

这可以通过使用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]+$'.

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

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

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

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

…或,用符号处理数字:

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

以下是我编写的脚本,用于与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