我无法弄清楚如何确保传递给我的脚本的参数是数字还是其他类型。
我想要做的只是像这样:
test *isnumber* $1 && VAR=$1 || echo "need a number"
需要帮助吗?
由于最近需要修改此代码,并且喜欢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; }
function
关键字,因为它没有任何有用的作用。此外,我不确定返回值的有用性。除非另有规定,否则函数将返回最后一个命令的退出状态,因此您不需要自己进行 return
。 - Tom Fenechreturn
语句会让代码变得混乱难读。使用function
关键字与否更多是个人口味问题,至少我从一行代码中移除了它们以节省空间。谢谢。 - 3ronco我使用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; }
我喜欢Alberto Zaccagni的答案。
if [ "$var" -eq "$var" ] 2>/dev/null; then
if [ "$var" -ge 0 ] 2> /dev/null; then ..
isnumber
的函数:#!/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
你也可以像这样使用 "let":
[ ~]$ var=1
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s a number
[ ~]$ var=01
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s a number
[ ~]$ var=toto
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s not a number
[ ~]$
但我更喜欢使用“=~”Bash 3+运算符,就像这个主题中的一些答案。
捕捉负数:
if [[ $1 == ?(-)+([0-9.]) ]]
then
echo number
else
echo not a number
fi
在这里我使用了一个正则表达式,用于测试整数部分和小数部分,它们用一个点号分隔。
re="^[0-9]*[.]{0,1}[0-9]*$"
if [[ $1 =~ $re ]]
then
echo "is numeric"
else
echo "Naahh, not numeric"
fi
a=''
和仅包含句点的字符串 a='.'
,因此你的代码有些错误... - gniourf_gniourfprintf '%b' "-123\nABC" | tr '[:space:]' '_' | grep -q '^-\?[[:digit:]]\+$' && echo "Integer." || echo "NOT integer."
如果您不接受负整数,请在grep匹配模式中删除-\?
。
test
命令:test $myVariable -eq 0 2>/dev/null
if [ $? -le 1 ]; then echo 'ok'; else echo 'KO'; fi
我找到了一个相当简短的版本:
function isnum()
{
return `echo "$1" | awk -F"\n" '{print ($0 != $0+0)}'`
}
test && echo "foo" && exit 0 || echo "bar" && exit 1
方法可能会产生一些意想不到的副作用 - 如果 Echo 失败了(也许输出到了一个关闭的FD),exit 0
将被跳过,然后代码将尝试echo "bar"
。如果这也失败了,&&
条件将失败,甚至不会执行exit 1
! 使用实际的if
语句而不是&&
/||
更不容易出现意外的副作用。 - Charles Duffy[[ $1 =~ "^[0-9]+$" ]] && { echo "number"; exit 0; } || { echo "not a number"; exit 1; }
大括号表示不应该在子shell中执行事情(如果使用圆括号()
就会明确这种情况)。注意:永远不要漏掉最后的分号。否则,你可能会导致bash打印出最丑陋(并且毫无意义)的错误消息... - syntaxerror[[ 12345 =~ ^ [0-9] + $]] && echo OKKK || echo NOOO
。 - Treviño