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

htt*_*ret 106 shell boolean

false; echo $?
Run Code Online (Sandbox Code Playgroud)

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

这有什么理由吗?

Car*_*rum 85

这是一个惯例,但是当你想到它时,它是一个特别有用的.一般来说,如果一个程序成功,那就是你需要知道的全部内容.但是,如果它失败了,你可能需要知道有关失败的各种信息 - 它为什么会发生,如何解决它等等.拥有零平均'成功'和非零意味着失败让你可以很容易地检查它是否成功,如果您愿意,可以调查特定错误以获取更多详细信息.许多API和框架都有类似的约定 - 成功返回0的函数和失败的函数会返回描述特定故障情况的错误代码.

  • 我理解这个答案,但我仍然不明白为什么bool to int conversion是颠倒的.是否存在"返回布尔约定":如果返回true,则表示没有错误,如果返回false,则表示发生错误(如"整数=错误代码约定"更为人熟知)? (6认同)
  • 假设存在布尔到 int 的转换意味着您并没有真正理解答案。零表示成功,所有 1、2、...、255 都是错误代码,可以有效地传达不同的故障情况。一个特殊的例子是“xargs”,它使用 127 左右范围内的不同错误代码来指示*组*命令如何失败。可以完成的转换是 int 到 bool,其中 0 映射到成功(我猜你想将其表示为 true / 1;但要意识到这只是另一个任意约定),所有其他值映射到失败。 (2认同)

Ste*_*ski 68

Bash是一种编程(脚本)语言,但它也是一个shell和一个用户界面.如果0是错误,那么程序只能出现一种错误.

但是在Bash中,任何非零值都是错误,我们可以使用1-255中的任何数字来表示错误.这意味着我们可以有许多不同类型的错误.1是一般错误,126意味着文件无法执行,127意味着'命令未找到',等等.这是一个带有特殊含义的Bash 退出代码列表,显示了一些最常见的退出代码.

还有很多种成功(退出状态0).但是,成功将允许您继续下一步 - 您可以将结果打印到屏幕,或执行命令等.

  • 这个实用的答案显示了各种返回代码的有用性,这比其他一些答案的预言更为可取. (6认同)
  • *"如果`0`是错误的,那么程序只能出现一种错误"*.这个陈述是关键,也是这个答案应该在顶部的原因. (3认同)
  • 一个伟大,简单和实用的解释.这需要在顶部. (2认同)
  • @LuisLavaire 这是未定义的行为。在实践中,这个数字往往会被截断。但如果运行时生成警告和/或只是崩溃,那绝对不会“更错误”。操作系统为该信息保留了一个字节,并且尝试放置多个字节肯定会出现错误。但操作系统设计者可能在第一天就遇到了崩溃,然后耸耸肩,决定他们能做的最好的事情就是截断值并继续前进。 (2认同)

axi*_*sty 25

这里有两个相关的问题.

首先,OP的问题,为什么0为真,但是shell中的false为1?第二,为什么应用程序返回0表示成功,非零表示失败?

要回答OP的问题,我们需要理解第二个问题.这篇文章的众多答案描述了这是一个惯例,并列出了这个惯例提供的一些细节.其中一些细节总结如下.

为什么应用程序返回0表示成功,非零表示失败?

调用操作的代码需要知道有关操作退出状态的两件事.操作是否成功退出?[*1]如果操作没有成功退出,为什么操作退出失败?任何值都可以用来表示成功.但是0比任何其他数字更方便,因为它可以在平台之间移植.总结xibo 对2011年8月16日此问题的回答:

零与编码无关.

如果我们想在一个32位整数字中存储一个(1),第一个问题是"big-endian word或little-endian word?",接着是"组成little-endian字的字节有多长? ",虽然零看起来总是一样的.

还需要预期的是,有些人会在某些时候将errno投入char或short,甚至浮动.(int)((char)ENOLCK)当char不是至少8位长(UNIX支持7位ASCII字符机器)时不是ENOLCK,而(int)((char)0)是0独立于char的建筑细节.

一旦确定0将是成功的返回值,则将任何非零值用于失败是有意义的.这允许许多退出代码回答操作失败的原因.

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

shell的基本用法之一是通过编写脚本来自动化进程.通常这意味着调用操作,然后根据操作的退出状态有条件地执行其他操作.菲利普A.在对这篇文章的回答中很好地解释了这一点

在bash和unix shell中,返回值不是boolean.它们是整数退出代码.

然后有必要将这些操作的退出状态解释为布尔值.将success(0)退出状态映射为true以及将任何非零/失败退出状态映射为false 是有意义的.这样做允许条件执行链式shell命令.

这是一个例子mkdir deleteme && cd $_ && pwd.因为shell将0解释为true,所以此命令可以按预期方便地工作.如果shell将0解释为false,那么您必须反转每个操作的解释退出状态.

简而言之,如果应用程序为成功的退出状态返回0的约定,那么shell将0解释为false是没有意义的.


[*1]:是的,很多时候操作需要返回的不仅仅是简单的成功消息,但这超出了这个线程的范围.

另请参阅"高级Bash-Scripting Guide"中的附录E.

  • 您好,只需强调一下,如果shell将零解释为false,将非零解释为true,那么执行`mkdir deleteme && cd _ $ && pwd`的技巧就不会真正失败。但是我们必须将其替换为`mkdir deleteme || cd _ $ || pwd`,在我看来还不太清楚,因为我们实际上想要做的是`mkdir deleteme`“ _and_”`cd _ $`“ _and_”`pwd ......(其中“ and”的含义是来自普通语言)。 (2认同)
  • 我想我在回答中已经涵盖了这一点。但需要明确的是,当您反转逻辑时,仅用“||”运算符替换“&&”运算符是不够的。您需要完全应用德摩根定律。请参阅:http://en.wikipedia.org/wiki/De_Morgan%27s_laws (2认同)

Phi*_* A. 17

我觉得重要的一个基本观点就是这个.在bash和unix shell中,返回值不是boolean.它们是整数退出代码.因此,您必须根据惯例评估它们,0表示成功,其他值表示一些错误.

test,[ ][[ ]]运营商时,bash条件的退出代码0(的结果/ bin中/真)的情况下评价为真.否则他们评价为假.

字符串的评估与退出代码不同:

if [ 0 ] ; then echo not null ; fi
if [ $(echo 0) ] ; then echo not null ; fi

if [ -z "" ] ; then echo null ; fi
Run Code Online (Sandbox Code Playgroud)

(( ))算术运算符解释1和0作为真假.但是,运营商不能作为一个完整的更换test,[ ][[ ]].下面是一个示例,显示算术运算符何时有用:

for (( counter = 0 ; counter < 10 ; counter ++ )) ; do
  if (( counter % 2 )) ; then echo "odd number $counter" ; fi
done
Run Code Online (Sandbox Code Playgroud)


Mat*_*hen 15

这只是一个惯例,0退出代码意味着成功. 几乎每个现代系统的EXIT_SUCCESS都为0.

编辑:

"为什么测试0和测试1都返回0(成功)?"

这是一个完全不同的问题.答案是将一个参数传递给test总是会导致成功,除非该参数是空字符串("").请参阅Open Group文档.

  • @httpinterpret,`test`不测试数值.它测试该字符串是否为空字符串.`man test`获取更多信息. (5认同)

Mic*_*zek 12

通常程序成功返回零,失败时返回非零; false返回1,因为它是一个方便的非零值,但通常任何非零值意味着某种类型的失败,并且许多程序将返回不同的非零值以指示不同的失败模式

  • 没有任何解释(或明显的原因)的沮丧和任何羞辱的人都是蹩脚的,因为他们根本没有帮助社区. (2认同)

mat*_*thk 6

AFAIK 这来自 C 约定,如果成功,您应该返回 0。看:

man close
Run Code Online (Sandbox Code Playgroud)

大多数 C (POSIX) api 都是这样构建的。 http://en.wikipedia.org/wiki/C_POSIX_library


小智 5

这是一个可以追溯到 Unix 早期的约定。

按照惯例,如果成功,所有系统调用都返回 0,否则返回非零,因为这样可以使用不同的数字来指示不同的失败原因。

Shell 遵循此约定,0 表示最后一个命令成功,否则为非零。类似地,非零返回值对于输出错误消息非常有用:例如 1:“脑死亡”,2:“无情”,等等。