我的外壳坏了吗?

时间:2015-09-25 23:31:57

标签: posix sh

#!/bin/sh
count=0
foo=0

echo "foo is $foo"

while [ "$foo" -eq 0 ] && [ "$count" -lt 10 ]; do
    echo "inside while: foo is $foo"
    count=$((count+1))
    foo=1
done

echo "after while"

您希望上面的脚本输出以下内容,对吧?

foo is 0
inside while: foo is 0
after while

它可以在许多其他机器上运行,就像你自己的机器一样。但不是我的......

foo is 0
inside while: foo is 0
inside while: foo is 1
inside while: foo is 1
... (infinite loop)

我做错了什么,或者我错过了一些明显的东西?

在这台(损坏?)机器上,如果我调整while条件以使用"过时" -a运算符,它"修复"问题(无论是什么)。为什么呢?

1 个答案:

答案 0 :(得分:1)

假设您的脚本文本中没有隐藏的字符(假设我建议您进行一些验证!),这确实表现出违反POSIX sh标准的行为。

  

n1 -eq n2 - 如果整数n1和n2在代数上相等则为真;否则,错误。

值得注意的是,如果任何一个参数实际上不是一个整数,那么就没有规定或保证会发生什么。例如,如果它一个整数,但在末尾有一个回车符或其他非打印字符。

要按顺序尝试的其他项目:

  • 运行sh -x yourscript,查看运行循环时调用test的确切参数。同时确定&&链中的第二个测试是否完全运行。
  • 将运算符从-eq更改为=,运行字符串比较而不是数字比较(从而确保包含隐藏字符的任何字符串都无法与字符串{{1}成功比较在这种情况下,而不是依赖于未定义的行为。)
  • 0替换为[ "$foo" -eq 0 ],并确保循环的内容不会运行(从而对shell的其他核心部分进行完整性检查)。