问题
#!/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"
You'd expect the script above to output the following, right?
foo is 0
inside while: foo is 0
after while
And it does on many other machines, like your own. But not mine ...
foo is 0
inside while: foo is 0
inside while: foo is 1
inside while: foo is 1
... (infinite loop)
Am I doing something wrong, or am I missing something obvious?
On this (broken?) machine, if I tweak the while
conditional to use the "obsolescent" -a
operator, it "fixes" the problem (whatever it is). Why?
回答1:
Assuming no hidden characters in your script text (an assumption I would suggest putting some effort into verifying!), this is indeed exhibiting behavior contrary to the POSIX sh standard.
n1 -eq n2
- True if the integers n1 and n2 are algebraically equal; otherwise, false.
Notably, this makes no specifications or guarantees about what happens if either argument is not in fact an integer; for instance, if it would be an integer, but has a carriage return or other nonprinting character on the end.
Other items to try, in order:
- Run
sh -x yourscript
, and look at the exact arguments called totest
when running the loop. Also determine whether the second test in the&&
chain is run at all. - Change your operator from
-eq
to=
, running a string comparison rather than a numeric comparison (and thereby ensuring that any string containing hidden characters will fail to compare successfully with the string0
, rather than relying on undefined behavior in this case). - Replace
[ "$foo" -eq 0 ]
withfalse
, and ensure that the contents of the loop do not run (thus sanity-checking some other core parts of the shell's implementation).
来源:https://stackoverflow.com/questions/32792035/is-my-shell-broken