2

我在 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 文件名进行调试。但是,它在比较时没有显示任何值(因为我没有使用 $ 符号)。

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

谢谢。

4

2 回答 2

6

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

在 bash 中:

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

...应该是正确的,因为(( ))(double parens) 进入了一个数字上下文,在该上下文中所有文本字符串都被视为变量并自动取消引用(并且在其中的操作符中,例如>and<具有其典型的算术含义,而不是执行重定向)。

你现在所做的很大程度上依赖于实现。[ a '>' b ]将是字母a和之间的字典比较b[ a -gt b ]是算术测试。

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

$ a=2; b=3; [ a -gt b ]; echo $?
-bash: [: a: integer expression expected
2

值得注意的是,这在 bash 的测试上下文内部是不同的[[ ]](它不带有 POSIX 语义[ ])。在那里,您所做的实际上确实(( ))有效,尽管它比表格更难阅读:

$ a=2; b=3; [[ a -gt b ]]; echo $?
1
$ a=3; b=2; [[ a -gt b ]]; echo $?
0

如果您仅限于 POSIX sh,则没有(( )),但确实$(( )),您可以使用几乎相同的方式:

$ a=2; b=3; result=$(( a > b ? 1 : 0 )); echo "$result"
0
$ a=3; b=2; result=$(( a > b ? 1 : 0 )); echo "$result"
1
于 2013-04-23T13:31:04.887 回答
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语句而言,打印到标准错误的错误消息仅仅是测试命令的副作用,并且完全被忽略。

于 2013-04-23T13:53:09.007 回答