false; echo $?
以上将输出1
,这与我所知道的所有其他编程语言相矛盾。
这有什么原因吗?
答案 0 :(得分:81)
这是一个惯例,但是当你想到它时,这是一个特别有用的惯例。一般来说,如果一个程序成功,那就是你需要知道的全部内容。但是,如果它失败了,你可能需要知道有关失败的各种信息 - 它为什么会发生,如何解决它等等。拥有零平均'成功'和非零意味着失败让你可以很容易地检查它是否成功,如果您愿意,可以调查特定错误以获取更多详细信息。许多API和框架都有类似的约定 - 成功返回0的函数和失败的函数会返回描述特定失败情况的错误代码。
答案 1 :(得分:64)
Bash是一种编程(脚本)语言,但它也是一个shell和一个用户界面。如果0
出错,则程序只能出现一种错误。
但是在Bash中,任何非零值都是错误,我们可以使用1-255中的任何数字来表示错误。这意味着我们可以有许多不同类型的错误。 1
是一般性错误,126
表示无法执行文件,127
表示“未找到命令”等。以下是Bash Exit Codes With Special Meanings的列表,其中显示了一些错误最常见的退出代码。
还有很多种成功(退出状态为0
)。但是,成功将允许您继续下一步 - 您可以将结果打印到屏幕,或执行命令等。
答案 2 :(得分:24)
此处有两个相关问题。
首先,OP的问题,为什么0为真但在shell中为false?,第二,为什么应用程序返回0表示成功,非零表示失败?< / em>
要回答OP的问题,我们需要了解第二个问题。这篇文章的众多答案描述了这是一个惯例,并列出了这个惯例提供的一些细节。其中一些细节总结如下。
为什么应用程序返回0表示成功,非零表示失败?
调用操作的代码需要知道有关操作退出状态的两件事。 操作是否成功退出? [* 1]如果操作未成功退出为什么操作退出失败?任何值都可用于表示成功。但是0比任何其他数字更方便,因为它可以在平台之间移植。总结xibo对2011年8月16日question的回答:
零与编码无关。
如果我们想在一个32位整数字中存储一个(1),那么第一个问题是“big-endian word或little-endian word?”,然后是“字节组成一小部分 - endian word?“,而零总是看起来一样。
还需要预期的是,有些人会在某些时候将errno转换为char或short,甚至浮动。 (int)((char)ENOLCK)当char不是至少8位长(UNIX支持7位ASCII字符机器)时不是ENOLCK,而(int)((char)0)是0独立于char的建筑细节。
一旦确定0将是成功的返回值,那么将任何非零值用于失败是有意义的。这允许许多exit codes回答操作失败的原因。
为什么0为真,但shell中的false为1?
shell的一个基本用法是通过编写脚本来自动化进程。通常这意味着调用操作,然后根据操作的退出状态有条件地执行其他操作。 Philippe A.在对这篇文章的回答中很好地解释了
在bash和unix shell中,返回值不是boolean。 它们是整数退出代码。
然后有必要将这些操作的退出状态解释为布尔值。将成功的(0
)退出状态映射为true以及将任何非零/失败退出状态映射为false是有意义的。这样做可以有条件地执行链式shell命令。
以下是mkdir deleteme && cd $_ && pwd
示例。因为shell将0解释为true,所以此命令可以按预期方便地工作。如果shell将0解释为false,那么您必须为每个操作反转解释的退出状态。
简而言之,如果应用程序为成功的退出状态返回0,那么shell将0解释为false是没有意义的。
[* 1]:是的,很多时候操作需要返回的不仅仅是简单的成功消息,但这超出了这个线程的范围。
另请参阅“高级Bash-Scripting Guide”中的Appendix E
答案 3 :(得分:15)
这只是一个惯例,0退出代码意味着成功。几乎在每个现代系统中EXIT_SUCCESS都为0。
编辑:
“为什么测试0和测试1都返回0(成功)?”
这是一个完全不同的问题。答案是将一个参数传递给test总是会导致成功,除非该参数是空字符串(“”)。请参阅Open Group documentation。
答案 4 :(得分:15)
我觉得重要的一个基本观点就是这个。在bash和unix shell中,返回值不是boolean。它们是整数退出代码。因此,您必须根据惯例评估它们,0表示成功,其他值表示一些错误。
对于test
,[ ]
或[[ ]]
运算符,如果退出代码为0(/ bin / true的结果),则bash条件的值为true。否则他们会评价为假。
字符串的评估方式与退出代码不同:
if [ 0 ] ; then echo not null ; fi
if [ $(echo 0) ] ; then echo not null ; fi
if [ -z "" ] ; then echo null ; fi
(( ))
算术运算符将1和0解释为true和false。但该运算符不能用作test
,[ ]
或[[ ]]
的完全替代。下面是一个显示算术运算符何时有用的示例:
for (( counter = 0 ; counter < 10 ; counter ++ )) ; do
if (( counter % 2 )) ; then echo "odd number $counter" ; fi
done
答案 5 :(得分:12)
通常程序成功返回零,失败时返回非零; false
返回1,因为它是一个方便的非零值,但通常任何非零值都意味着某种类型的失败,并且许多程序将返回不同的非零值以指示不同的失败模式
答案 6 :(得分:4)
AFAIK来自C约定,如果成功,你应该返回0。 参见:
man close
大多数C(POSIX)api都是这样构建的。 http://en.wikipedia.org/wiki/C_POSIX_library
答案 7 :(得分:3)
您试图将真/假等同于成功/失败。
他们完全是两个,虽然一开始就是微妙的,但不同的二分法!
在shell脚本中,没有true / false这样的东西。 Shell'表达式'不会被解释为true / false。相反,shell'表达式'是成功或失败的过程。
显然,一个过程可能由于多种原因而失败。因此,我们需要更大的设置代码来映射可能的故障。正整数可以解决这个问题。另一方面,如果过程成功,那意味着它完全按照预期的方式完成。由于只有一种方法,我们只需要一个代码。 0可以解决问题。
在C中,我们正在创建一个程序。在shell脚本中,我们运行了一堆程序来完成某些任务。
差分!
答案 8 :(得分:3)
这是一个可以追溯到Unix早期的惯例。
按照惯例,所有系统调用如果成功则返回0,否则返回非零,因为这样可以使用不同的数字来表示不同的失败原因。
Shells遵循此约定,0表示最后一个命令成功,否则为非零。类似地,非零返回值对于输出错误消息很方便:例如, 1:&#34;脑死亡&#34;,2:&#34;无情&#34;等等。
答案 9 :(得分:1)
也许记住它的好方法是:
答案 10 :(得分:0)
尽管该问题没有针对 C 编程进行标记,而且大多数答案似乎间接解释了真正的原因,但我想我会回答,我希望 C 程序员会发现有用的内容。
恕我直言,歧义的真正来源是 C 标准。例如,在 C11 草案规范的 (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) 部分“7.22.4.4 退出函数”与“7.18 布尔类型和值
引自 C11 草案规范 (https://stackoverflow.com/a/40009047/4726668):
7.22.4.4 退出函数
”
5 最后,控制权返回给宿主环境。如果状态值为零或 EXIT_SUCCESS,则返回状态成功终止的实现定义形式。如果状态的值为 EXIT_FAILURE,则返回状态不成功终止的实现定义形式。否则返回的状态是实现定义的。
”
对比
7.18 布尔类型和值
”
3 其余三个宏适用于#if 预处理指令。他们是
真实
展开为整数常数 1,
假
它扩展为整数常量 0,和
_ _bool_true_false_are_defined
它扩展为整数常量 1。
”