所以我很理解退出代码0
被认为是程序运行成功。然后我们在 bash 脚本中使用它,AND
并OR
根据第一个程序的退出状态运行下一个程序。一个很好的例子可以在这里找到:https://unix.stackexchange.com/a/187148/454362
这是否意味着0
被解释为真,而除零之外的任何其他数字都被解释为假?这与我所知道的所有编程语言相反。那么我可以假设 bash 内部使用逻辑NOT
将退出代码反转为正确的 false / true 值吗?
所以,这些是一些例子:
#should result in false, and bash shows 0 as false
echo $(( 1 && 0 ))
# should result in true, and bash shows 1 as true
echo $(( 1 || 0 ))
# does not show 'hi'; even though if false is zero per first example, then
# this should be considered success exit code and 'hi' to be shown!!
false && echo 'hi'
# does show 'hi'. It first runs the "echo 'hi'" and interprets its exit
# status of zero as success, but then false stops the 2nd hi.
echo 'hi' && false && echo ' 2nd hi'
# shows 'hi 2nd hi'
echo 'hi' && (( 1 || 0 )) && echo ' 2nd hi'
看来我正在回答我自己的问题。但我只是想澄清是否有人知道 bash 处理的内部。
答案1
您链接到的帖子中的示例如下:
false && echo "OK"
true || echo "OK"
在这种情况下,对于进程的退出状态,是的,0
是真实的,其他任何东西都是虚假的。 (是的,这里true
是false
程序。可能是内置于 shell 中的,但工作原理是一样的。)
AND 列表
控制运算符“&&”表示 AND 列表。格式应为: 第一
command1 [ && command2] ...
命令1应予执行。如果其退出状态为零,命令2应被处决,等等……
是的,这与几乎所有其他上下文和编程语言中使用的约定相反。话又说回来,在 C 语言中,函数在成功时返回零,在错误时返回非零错误代码也很常见。这样,您就可以区分不同类型的错误(*)。当然,如果您的函数需要返回一些有用的值(例如指针),那么这实际上不起作用,并且就 C 语言而言,0 是假的。无论如何,都是不同的。
我认为对实施进行任何假设都不是一个好主意。请记住,在这种情况下,零为真,例如 (true && true) 为 (true)。
(*就像家庭一样,快乐的系统调用都是相似的。不快乐的系统调用各有各的不快乐。)
然后你的例子:
#should result in false, and bash shows 0 as false
echo $(( 1 && 0 ))
在这里,您在算术上下文中使用&&
,它不遵守与退出状态相同的规则。这里,0为假,1为真。 (true AND false)也是如此1 && 0
,即 (false) 或 0。
# should result in true, and bash shows 1 as true
echo $(( 1 || 0 ))
与上面类似。
# does not show 'hi'; even though if false is zero per first example, then
# this should be considered success exit code and 'hi' to be shown!!
false && echo 'hi'
这实用程序称为false
以状态 1(或至少某个非零值)退出。在这种情况下,这是错误的,因此&&
通过短路逻辑跳过了右侧。
# does show 'hi'. It first runs the "echo 'hi'" and interprets its exit
# status of zero as success, but then false stops the 2nd hi.
echo 'hi' && false && echo ' 2nd hi'
一样。
# shows 'hi 2nd hi'
echo 'hi' && (( 1 || 0 )) && echo ' 2nd hi'
您1 || 0
在这里使用了,无论哪种方式都是正确的,并且数值在算术上下文中有些消失了。让我们试试这些:
$ echo foo && (( 0 )) && echo bar
foo
$ echo foo && (( 1 )) && echo bar
foo
bar
现在,((...))
是一个算术构造(如$((...))
),其中 0 为假。与 不同$((...))
,((...))
也是一个命令,因此具有退出状态。如果内部表达式的计算结果为非零(真值),则它以零(真值)退出;如果内部表达式的计算结果为零(假),则为 1(假)。好吧,这可能会令人困惑,但最终结果是,类似 C 的隐式比较在它内部与零工作,并且当将它与 shell 的条件一起使用时,您会得到相同的真值。
因此,while (( i-- )); do ...
循环直到i
为零。
((( foo ))
不是标准的,但受 ksh/Zsh/Bash 支持。它的标准解释是foo
两个嵌套子 shell 内的命令,因此可能会给出“命令 'foo' 未找到”错误。)
还值得指出的是,类似的东西(( true )) && echo maybe
可能不会打印任何内容。在算术上下文中,普通单词被视为变量的名称(在许多 shell 中递归地),因此除非将变量true
设置为非零值,否则(( true ))
将为 false。
(来自混淆部门的想法是运行true=0; false=1; true() (exit 1); false() (exit 0);
。现在打印什么 true && (( false )) || echo maybe && echo maybe not
以及为什么?。)
答案2
是的,命令退出状态反转了整数和真/假概念之间的通常映射。
原因是命令可能会以多种不同的方式失败。只有一个零值,但有许多非零值(在本例中为 255,因为仅使用了退出状态的 8 位)。通过使用非零作为故障表示,您可以使用不同的非零值来编码不同类型的故障。
例如,grep
当成功读取文件但未找到任何匹配项时,使用退出状态 1;当出现实际错误时,使用状态 2。
如果您的应用程序不关心故障模式之间的区别,您可以false
通过使用if
或 逻辑运算符将它们全部视为。如果你关心的话,你就会$?
明确地进行比较。
这种为不同退出状态分配不同含义的方法并不常见,但在需要时使用它会很有用。1
如果不需要区分,大多数程序只是将其用作失败代码。
true
echo $? # 0
false
echo $? # 1
答案3
该行为取决于外壳。假设您正在使用 Bash,答案来自 Bash 手册:
列表
...
AND 和 OR 列表是分别由
&&
和||
控制运算符分隔的一个或多个管道的序列。 AND 和 OR 列表以左关联性执行。 AND 列表的形式为command1 && command2
command2
command1
当且仅当返回退出状态为零(成功)时才执行。OR 列表的形式为
command1 || command2
command2
command1
当且仅当返回非零退出状态时才执行。 AND 和 OR 列表的返回状态是列表中最后执行的命令的退出状态。