为什么[a -gt b](不是[“$ a”-gt“$ b”])似乎有效?

时间:2013-04-23 13:27:30

标签: shell unix sh

我在unix shell脚本中遇到一个问题。让我用非常简单的例子问你。

假设,我正在收到用户输入并比较两个数字。

echo "Enter the first number"
read a
echo "Enter the second number"
read b
if [ a -gt b ]---------------------->I have not used $ before variable name.
then
    echo "a is greater"
else
    echo "b is greater"
fi

在这个例子中,我应该使用$来获取变量的值。错了,我忘记了。不过,它给了我正确的结果,如何以及为什么?

我尝试使用sh -x filename进行调试。但是,它在比较时没有显示任何价值(因为我没有使用$符号)。

shell如何决定哪个更大,反之亦然? 它内部如何工作?

感谢。

2 个答案:

答案 0 :(得分:6)

值得注意的是,如果您在数字上下文中进行了比较,那么可以在没有$的情况下使用它。

在bash中:

if (( a > b )); then
  echo "a is greater"
else
  echo "b is greater"
fi

...是正确的,因为(( ))(双重parens)进入一个数字上下文,其中所有文本字符串都被视为变量并自动解引用(以及>和{之类的运算符{1}}具有典型的算术含义,而不是执行重定向。)

您现在正在做的是严重依赖于实现。 <将是字母[ a '>' b ]a之间的字母比较。 b是算术测试。

许多炮弹根本不允许这样做。例如:

[ a -gt b ]

值得注意的是,这在bash的$ a=2; b=3; [ a -gt b ]; echo $? -bash: [: a: integer expression expected 2 测试上下文中是不同的(它不带有[[ ]]的POSIX语义)。在那里,你正在做什么 工作,虽然它比[ ]形式更难阅读:

(( ))

如果您仅限于POSIX sh,则表示您没有$ a=2; b=3; [[ a -gt b ]]; echo $? 1 $ a=3; b=2; [[ a -gt b ]]; echo $? 0 ,但(( )),您可以使用几乎相同的方式:< / p>

$(( ))

答案 1 :(得分:2)

有一个简单的解释为什么你的测试似乎有效:它盲目地执行else子句。

除了退出非零退出状态外,[ ... ]内置无法向调用者报告错误。顺便提及,非零退出状态也用于表示“假”。这意味着if无法区分对其条件的错误和错误评估,这就是为什么您的比较总是更喜欢else分支并因此看起来有效的原因。您可以通过恢复参数来轻松测试它:

$ if [ b -gt a ]
then
    echo "b is greater"
else
    echo "a is greater"
fi
dash: 11: [: Illegal number: b
a is greater

请注意,就if语句而言,打印到标准错误的错误消息仅仅是测试命令的副作用,并且完全被忽略。