我在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如何决定哪个更大,反之亦然? 它内部如何工作?
感谢。
答案 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
语句而言,打印到标准错误的错误消息仅仅是测试命令的副作用,并且完全被忽略。