为什么0为真,但shell中的false为1?

时间:2010-05-29 04:50:50

标签: shell boolean

false; echo $?

以上将输出1,这与我所知道的所有其他编程语言相矛盾。

这有什么原因吗?

11 个答案:

答案 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)

也许记住它的好方法是:

  • 返回码回答“答案是什么?”正确(或其他结果)或错误
  • 退出代码回答“出了什么问题?”退出代码或没有问题(0)

答案 10 :(得分:0)

尽管该问题没有针对 C 编程进行标记,而且大多数答案似乎间接解释了真正的原因,但我想我会回答,我希望 C 程序员会发现有用的内容。

恕我直言,歧义的真正来源是 C 标准。例如,在 C11 草案规范的 (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) 部分“7.22.4.4 退出函数”与“7.18 布尔类型和值 ”部分中,EXIT_SUCCESS 为零,这是从 linux 运行的程序shell cmdline 预计会在成功时返回,而 bool true 是非零的(#define'ed 为 1,但将其称为非零更安全。为什么会这样?请参阅 https://stackoverflow.com/users/827263/keith-thompson 中的注释 { {3}} ).

引自 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。