Is my shell broken?

℡╲_俬逩灬. 提交于 2020-01-07 11:29:05

问题


#!/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 to test 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 string 0, rather than relying on undefined behavior in this case).
  • Replace [ "$foo" -eq 0 ] with false, 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!