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

我只想这样做:

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

有什么帮助吗?


当前回答

我在看答案。。。意识到没有人想到浮点数(带点)!

使用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]+$`

其他回答

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

我找到了一个很短的版本:

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

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

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

如果是数字,则乘以1将得到相同的值(包括负数)。否则,您将得到空值,您可以进行测试

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

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

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

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

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

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

现在还不能评论,所以我将添加我自己的答案,这是使用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))更宽容。我的单元测试只测试整数或浮点值,但不测试任何无效输入。