BASH:testingstring是否作为整数有效?
我正在尝试做一些足够普通的事情:在shell脚本中parsing用户input。 如果用户提供了一个有效的整数,那么脚本会做一件事情,如果无效的话,它会做其他事情。 麻烦的是,我还没有find一个简单的(合理的,优雅的)做这个方法 – 我不想一个一个的字符。
我知道这一定很容易,但我不知道如何。 我可以用十几种语言做,但不是BASH!
在我的研究中,我发现这一点:
正则expression式来testing一个string是否包含以10为底的有效实数
在那里有一个关于正则expression式的答案,但据我所知,这是C语言中的一个函数(等等)。 尽pipe如此,它看起来像一个很好的答案,所以我尝试了与grep,但grep不知道该怎么办。 我尝试了-P,在我的盒子上意味着把它当作PERL regexp – nada。 短跑E(-E)也没有工作。 而且-F。
只是要清楚,我正在尝试这样的事情,寻找任何输出 – 从那里,我将破解剧本利用我得到的任何东西。 (IOW,我期待一个不合格的input不会在有效的行重复时返回。)
snafu=$(echo "$2" | grep -E "/^[-+]?(?:\.[0-9]+|(?:0|[1-9][0-9]*)(?:\.[0-9]*)?)$/") if [ -z "$snafu" ] ; then echo "Not an integer - nothing back from the grep" else echo "Integer." fi
有人请说明这是如何做到最简单吗?
坦率地说,在我看来,这是TEST的一个短暂的过程。 它应该有这样的旗帜
if [ -I "string" ] ; then echo "String is a valid integer." else echo "String is not a valid integer." fi
谢谢。
[[ $var =~ ^-?[0-9]+$ ]]
-
^
表示input模式的开始 -
-
是一个文字“ – ” - 这个
?
意思是“前面(-
)”的0或1 -
+
表示“前面([0-9]
)”中的一个或多个“ -
$
表示input模式的结束
所以正则expression式匹配一个可选项-
(对于负数的情况),后跟一个或多个十进制数字。
参考文献
哇…这里有很多好的解决scheme! 在上面的所有解决scheme中,我同意@nortally使用-eq
单行是最酷的。
我正在运行GNU bash,版本4.1.5(Debian)。 我也检查过这个ksh(SunSO 5.10)。
这是我的版本检查如果$1
是一个整数或不是:
if [ "$1" -eq "$1" ] 2>/dev/null then echo "$1 is an integer !!" else echo "ERROR: first paramter must be an integer." echo $USAGE exit 1 fi
这也是卡特尔-ve数,其中一些上述解决scheme将有一个错误的否定结果,它将允许前缀“+”例如+30,这显然是一个整数。
结果:
$ int_check.sh 123 123 is an integer !! $ int_check.sh 123+ ERROR: first paramter must be an integer. $ int_check.sh -123 -123 is an integer !! $ int_check.sh +30 +30 is an integer !! $ int_check.sh -123c ERROR: first paramter must be an integer. $ int_check.sh 123c ERROR: first paramter must be an integer. $ int_check.sh c123 ERROR: first paramter must be an integer.
Ignacio Vazquez-Abrams提供的解决scheme在解释之后也非常整洁(如果你喜欢regex的话)。 但是,它不会使用+
前缀来处理正数,但是可以很容易地将其固定为:
[[ $var =~ ^[-+]?[0-9]+$ ]]
这里晚会迟到了。 我非常惊讶,没有一个答案提到最简单,最快,最便携的解决scheme; case
陈述。
case ${variable#[-+]} in *[!0-9]* | '') echo Not a number ;; * ) echo Valid number ;; esac
在比较之前对任何符号进行修剪就像是一种破解,但是这使得case语句的expression更为简单。
为了便携到Bash 3.1(当引入=~
testing时),使用expr
。
if expr "$string" : '-\?[0-9]\+$' >/dev/null then echo "String is a valid integer." else echo "String is not a valid integer." fi
expr STRING : REGEX
searchREGEX锚定的REGEX,回显第一个组(或者匹配长度,如果没有),并返回成功/失败。 这是旧的正则expression式语法,因此超出\
。 -\?
意思是“可能-
”, [0-9]\+
表示“一个或多个数字”,而$
表示“string的结尾”。
Bash也支持扩展的球体,但我不记得从哪个版本开始。
shopt -s extglob case "$string" of @(-|)[0-9]*([0-9])) echo "String is a valid integer." ;; *) echo "String is not a valid integer." ;; esac # equivalently, [[ $string = @(-|)[0-9]*([0-9])) ]]
@(-|)
表示“ -
或没有”, [0-9]
表示“数字”, *([0-9])
表示“零个或多个数字”。
我喜欢使用-eq
testing的解决scheme,因为它基本上是一个单线程。
我自己的解决scheme是使用参数扩展来丢弃所有的数字,看看是否还有剩下的东西。 (我还在使用3.0,还没有用过[[
或者以前的expr
,但很高兴见到他们。)
if [ "${INPUT_STRING//[0-9]}" = "" ]; then # yes, natural number else # no, has non-numeral chars fi
这里还有另一个(只使用testing内置命令和它的返回码):
function is_int() { return $(test "$@" -eq "$@" > /dev/null 2>&1); } input="-123" if $(is_int "${input}"); then echo "Input: ${input}" echo "Integer: $[${input}]" else echo "Not an integer: ${input}" fi
您可以去除非数字并进行比较。 这是一个演示脚本:
for num in "44" "-44" "44-" "4-4" "a4" "4a" ".4" "4.4" "-4.4" "09" do match=${num//[^[:digit:]]} # strip non-digits match=${match#0*} # strip leading zeros echo -en "$num\t$match\t" case $num in $match|-$match) echo "Integer";; *) echo "Not integer";; esac done
这是testing输出的样子:
44 44整数 -44 44整数 44-44不是整数 4-4 44不是整数 a4 4不是整数 4a 4不是整数 .4 4不是整数 4.4 44不是整数 -4.4 44不是整数 09 9不是整数
对我来说,最简单的解决scheme是使用(())
expression式中的variables,如下所示:
if ((VAR > 0)) then echo "$VAR is a positive integer." fi
当然,这个解决scheme只有在零值对你的应用没有意义时才是有效的。 在我的例子中碰巧是这样,这比其他解决scheme简单得多。
正如在注释中指出的那样,这会使您受到代码执行攻击: (( ))
运算符评估VAR
,如bash(1)手册页的Arithmetic Evaluation
部分所述 。 因此,当VAR
内容的来源不确定时,您不应该使用这种技术(当然,您也不应该使用任何其他forms的可变扩展)。
或与sed:
test -z $(echo "2000" | sed s/[0-9]//g) && echo "integer" || echo "no integer" # integer test -z $(echo "ab12" | sed s/[0-9]//g) && echo "integer" || echo "no integer" # no integer
添加到伊格纳西奥·巴斯克斯 – 艾布拉姆斯的答案。 这将允许+符号在整数之前,它将允许任意数量的小数点作为小数点。 例如,这将允许+45.00000000被视为一个整数。
但是,$ 1必须格式化为包含小数点。 45在这里不被认为是一个整数,但45.0是。
if [[ $1 =~ ^-?[0-9]+.?[0]+$ ]]; then echo "yes, this is an integer" elif [[ $1 =~ ^\+?[0-9]+.?[0]+$ ]]; then echo "yes, this is an integer" else echo "no, this is not an integer" fi