【问题标题】:How can I test if a variable is *not* a positive integer?如何测试变量是否*不是*正整数?
【发布时间】:2012-06-09 14:07:59
【问题描述】:

测试一个变量是否是例如一个大于 0 的数字,你可以这样写:

((i > 0))

但是我将如何测试变量是否为not 一个大于 0 的数字?

编辑

抱歉打错字了,意思是not a number greater than 0

编辑 2

抱歉这个可怜的问题。变量的值作为命令行参数传递,因此它可能是数字,也可能不是。这也需要检查。

【问题讨论】:

  • (!(i>10)) 我不记得语法但希望对您有所帮助
  • 我觉得这个问题只要用谷歌搜索一下就可以回答...
  • google -> "bash 测试比较"
  • 谁曾经使用过-gt:这在一般情况下无法测试变量是否为数字。它不起作用,因为在算术表达式中,如果变量不是数字,它的计算结果为 0
  • 我不明白为什么这个问题被否决了。这是一个有效的问题。

标签: bash


【解决方案1】:

要检查不是数字,您必须使用正则表达式进行测试。我使用-5 而不是0 只是为了演示更一般的情况(我的假设是您使用整数):

#!/bin/bash

A=$1

if [[ $A =~ ^[\-0-9]+$ ]] && (( A > -5)); then
  echo "A is number and is greater then -5"
else
  echo "A is not a number or is <= -5"
fi

如果你想测试非整数,你必须在你的问题中澄清什么被认为是数字。

【讨论】:

  • -1:使用正则表达式是绝对错误的。 test 是专门为这种类型的比较而设计的,使用它会更不脆弱、更易读、更快。
  • 任何编程语言中的数字文字都是根据“正则表达式”定义的。我不明白这怎么可能是错的。
  • 这是错误的,因为显式测试数字是否大于 0 比正则表达式字符串比较更容易理解,更有效,并且更不容易出现编程错误。使用[[ 而不是test 会强制您进行这个字符串比较,所以这里的问题有两个:应该使用test 而不是[[,因为使用[[ 会强制进行正则表达式比较,它没有放在这里。
【解决方案2】:

比较

Shell ArithmeticBash Conditional Expressions 的 Bash 手册部分清楚地介绍了这一点。

# Shell arithmetic
$ (( -1 <= 0 )); echo $?
0

# Conditional expression
$ [[ -1 -le 0 ]]; echo $?
0

# Negated conditional. Confusing, but possible.
[[ ! -1 -gt 0 ]]; echo $?
0

简单吧?

验证

但是,如果您在执行比较之前尝试测试该数字是否实际上是整数,那么您可以使用这样的复合表达式来验证和比较名为 int 的变量:

[[ "$int" =~ ^[-+]?([1-9][[:digit:]]*|0)$ && "$int" -le 0 ]]

请注意,比较确定验证的整数是否“小于或等于零”,而不是否定它是正整数的断言。因此,只有当正则表达式验证为(可能有符号的)整数时,整个表达式才会返回 true(例如,退出状态为零)并且如果整数是有符号的负整数。

当然还有其他方法可以构造这个表达式,但这是一个相当易读(如果相当 Bash 特定)的解决方案。

相关链接

【讨论】:

  • [^-]? 表示可选的非连字符。您可能指的是^-?,这意味着字符串开头的可选连字符。虽然您的 -gt 测试表明您正在寻找一个正整数,但您的正则表达式缺乏通用性,因为它不包括零(同时包括正整数和负整数)。
  • @DennisWilliamson 感谢您的反馈。整个表达式实际上有一些反转的逻辑(现在已修复),但关键是表达式的前半部分除了验证“完整性”之外没有任何其他用途。诚然,可以构建一个正则表达式来替换当前的验证和比较步骤(例如^-[[:digit:]]+|^0$),但我认为将这些步骤分开可以更清楚地传达意图。 YMMV。
【解决方案3】:

简单的正则表达式可以允许非数字,例如“11--22--99”(尽管它们确实在 (()) 内进行数学计算)。

下面的正则表达式只允许 0 或不带前导零的负整数并拒绝负零。

for a in 0 -0 00 -1 -01 1 1-1 --1
do
    if [[ $a =~ ^(-[1-9][0-9]*|0)$ ]]
    then
        echo "[+] $a passes"
    else
        echo "[X] $a doesn't"
    fi
done

输出:

[+] 0 passes
[X] -0 doesn't
[X] 00 doesn't
[+] -1 passes
[X] -01 doesn't
[X] 1 doesn't
[X] 1-1 doesn't
[X] --1 doesn't

此时,您实际上不需要为((a &lt;= 0)) 添加测试,尽管您可以测试它是否小于或等于某个较小的数字。

编辑:

您可以将整数验证测试放在一个函数中并单独进行比较以提高可读性,如下所示:

isint () {
    [[ $1 =~ ^(-?[1-9][0-9]*|0)$ ]] # use [+-]? instead of -? to allow "+"
}

if isint "$var" && ((var <= 0))
then
    echo "validated and compared: $var"
else
    echo "non-integer or out of range: $var"
fi

【讨论】:

  • 我喜欢将正则表达式测试提取到函数的想法。它确实使有条件的眼睛更友好。感谢您发布出色的替代结构。
【解决方案4】:

是的,我意识到这个问题被标记为 bash,但没有理由不这样做是一种可移植的方式:

if ! test "$i" -gt 0 2> /dev/null ; then
   echo $i is not a positive integer
fi

【讨论】:

  • +1。不过,当明确提到 Bash 时,我仍然更喜欢使用 Bash 构造。 ;)
【解决方案5】:
i=15
if [[ ! $i -gt 10 ]]; then
        echo "lalala"
fi

【讨论】:

  • @Achshar 我不同意。 Bash [[ 不会出错。该脚本将返回结果lalala
猜你喜欢
  • 2011-04-07
  • 2022-01-25
  • 2010-10-22
  • 2016-07-27
  • 2018-09-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多