【发布时间】:2010-09-23 12:15:07
【问题描述】:
如何在 UNIX shell 中检查变量是数字还是包含数字?
【问题讨论】:
-
标题询问变量是否为数字,描述询问变量是否包含数字。你要哪个?另外,当您说数字时,您的意思是整数还是应该处理小数?
-
你认为 3.1415 是一个数字吗?
如何在 UNIX shell 中检查变量是数字还是包含数字?
【问题讨论】:
if echo $var | egrep -q '^[0-9]+$'; then
# $var is a number
else
# $var is not a number
fi
【讨论】:
echo $var | egrep -q '^-*[[:digit:]]+$' && echo is num || echo not num(当然,仅适用于基数 10)。这甚至适用于过度否定但合法的数字,如 ----234。
Shell变量没有类型,所以最简单的方法是使用返回类型test命令:
if [ $var -eq $var 2> /dev/null ]; then ...
(或者用正则表达式解析)
【讨论】:
if [ -n "$var" -a $var -eq $var 2> /dev/null ]; then echo is num; else echo not a num; fi
echo $((--234 * 2))),但它会失败。
没有叉子,没有管道。纯 POSIX 外壳:
case $var in
(*[!0-9]*|'') echo not a number;;
(*) echo a number;;
esac
(假设 number := 一串数字)。如果您还想允许带有单个前导 - 或 + 的签名数字,请像这样去掉可选符号:
case ${var#[-+]} in
(*[!0-9]*|'') echo not a number;;
(*) echo a number;;
esac
【讨论】:
在启用 extglob 选项的 ksh93 或 bash 中:
if [[ $var == +([0-9]) ]]; then ...
【讨论】:
if [[ $var == +(-*[[:digit:]]) ]]; then echo is num; else echo not num; fi。很好,这可以处理空的或未设置的 var 以及多字 var(例如,“棕牛”)。使用[:xdigit:] 字符类作为基数为 16 的数字。注意:与语言环境无关的字符类(例如 [:digit:])似乎不适用于 ksh。
这是一个仅使用基本外壳中可用功能的版本(即它可以在sh 中工作),并且比使用grep 少一个进程:
if expr "$var" : '[0-9][0-9]*$'>/dev/null; then
echo yes
else
echo no
fi
这会检查$var 是否仅代表一个整数;调整正则表达式以适应口味,并注意 expr 正则表达式参数隐式锚定在开头。
【讨论】:
expr "$var" : '-*[0-9][0-9]*$' && echo num || echo not num
这可以使用正则表达式进行检查。
###
echo $var|egrep '^[0-9]+$'
if [ $? -eq 0 ]; then
echo "$var is a number"
else
echo "$var is not a number"
fi
【讨论】:
我是 shell 编程的新手,所以我尝试找出最简单易读的方法 它只会检查 var 是否大于或等于 0 我认为这是选择参数的好方法......可能不是以前的......:
if [ $var -ge 0 2>/dev/null ] ; then ...
【讨论】:
if echo "$var" | egrep -q '^\-?[0-9]+$'; then
echo "$var is an integer"
else
echo "$var is not an integer"
fi
测试(var=2 等):
2 is an integer
-2 is an integer
2.5 is not an integer
2b is not an integer
if echo "$var" | egrep -q '^\-?[0-9]*\.?[0-9]+$'; then
echo "$var is a number"
else
echo "$var is not a number"
fi
测试(var=2 等):
2 is a number
-2 is a number
-2.6 is a number
-2.c6 is not a number
2. is not a number
2.0 is a number
【讨论】:
if echo $var | egrep -q '^[0-9]+$'
实际上,如果 var 是多行,这不起作用。
即
var="123
qwer"
特别是如果 var 来自文件:
var=`cat var.txt`
这是最简单的:
if [ "$var" -eq "$var" ] 2> /dev/null
then echo yes
else echo no
fi
【讨论】:
-n "$var" 以捕获空/未设置的变量)。见那里的cmets。关于多行问题的潜在误报的好点。
这里是没有任何正则表达式的测试(tcsh 代码):
创建文件校验码:
#! /usr/bin/env tcshif ( "$*" == "0" ) then
exit 0 # number
else
((echo "$*" | bc) > /tmp/tmp.txt) >& /dev/null
set tmp = `cat /tmp/tmp.txt`
rm -f /tmp/tmp/txt
if ( "$tmp" == "" || $tmp == 0 ) then
exit 1 # not a number
else
exit 0 # number
endif
endif
然后运行
chmod +x checknumber
使用
checknumber -3.45
你会得到错误级别的结果 ($?)。
您可以轻松优化它。
【讨论】:
( test ! -z "$num" && test "$num" -eq "$num" 2> /dev/null ) && {
# $num is a number
}
【讨论】:
-z 检查真的有必要吗? test "" -eq "" 2>/dev/null 符合我的预期(标准 macOS 上的旧 Bash 3.2)。无论如何,括号似乎是多余的(并且会花费您不必要的子shell)。
您可以使用简单的测试命令来做到这一点。
$ test ab -eq 1 >/dev/null 2>&1
$ echo $?
2
$ test 21 -eq 1 >/dev/null 2>&1
$ echo $?
1
$ test 1 -eq 1 >/dev/null 2>&1
$ echo $?
0
所以如果退出状态是 0 或 1 则它是一个整数,但如果存在状态是 2 则它不是一个数字。
【讨论】:
a=123
if [ `echo $a | tr -d [:digit:] | wc -w` -eq 0 ]
then
echo numeric
else
echo ng
fi
数字
a=12s3
if [ `echo $a | tr -d [:digit:] | wc -w` -eq 0 ]
then
echo numeric
else
echo ng
fi
ng
【讨论】:
tr -d -。
从命令行获取值并显示 THE INPUT IS DECIMAL/NON-DECIMAL 和 NUMBER 与否:
NUMBER=$1
IsDecimal=`echo "$NUMBER" | grep "\."`
if [ -n "$IsDecimal" ]
then
echo "$NUMBER is Decimal"
var1=`echo "$NUMBER" | cut -d"." -f1`
var2=`echo "$NUMBER" | cut -d"." -f2`
Digit1=`echo "$var1" | egrep '^-[0-9]+$'`
Digit2=`echo "$var1" | egrep '^[0-9]+$'`
Digit3=`echo "$var2" | egrep '^[0-9]+$'`
if [ -n "$Digit1" ] && [ -n "$Digit3" ]
then
echo "$NUMBER is a number"
elif [ -n "$Digit2" ] && [ -n "$Digit3" ]
then
echo "$NUMBER is a number"
else
echo "$NUMBER is not a number"
fi
else
echo "$NUMBER is not Decimal"
Digit1=`echo "$NUMBER" | egrep '^-[0-9]+$'`
Digit2=`echo "$NUMBER" | egrep '^[0-9]+$'`
if [ -n "$Digit1" ] || [ -n "$Digit2" ]; then
echo "$NUMBER is a number"
else
echo "$NUMBER is not a number"
fi
fi
【讨论】: