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 : REGEXsearchREGEX锚定的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])表示“零个或多个数字”。

我喜欢使用-eqtesting的解决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