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

我只想这样做:

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

有什么帮助吗?


当前回答

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

数字将包括空格、小数点和“e”或“e”表示浮点。

但是,如果指定C样式十六进制数,即“0xffff”或“0xffff”,则[[:digital:]]返回true。这里有点陷阱,bash允许你做一些类似“0xAZ00”的事情,但仍然将其算作一个数字(这不是GCC编译器的一些奇怪的怪癖,允许你对16以外的基使用0x符号吗??)

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

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

其他回答

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

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

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

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

…或,用符号处理数字:

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

因为我最近不得不修改这个,并且最喜欢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()包含破折号、逗号和指数符号,因此在整数和浮点数上返回TRUE,而另一方面,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; }

这将测试数字是否为非负整数。它是独立于外壳的(即没有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所建议的那样。

几乎是你想要的语法。只需要一个函数编号:

#!/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 

这是一个有点粗糙的边缘,但有点新手友好。

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

这将导致一个错误,如果$number不是一个数字,则会打印“非法数字:”,但它不会跳出脚本。奇怪的是,我找不到一个测试选项来测试整数。这里的逻辑将匹配任何大于或等于0的数字。