管道中“$?”的正确值是多少?

What is the correct value of `$?` in a pipeline?

提问人:William Pursell 提问时间:4/18/2015 最后编辑:William Pursell 更新时间:4/18/2015 访问量:266

问:

我发现以下行为有点不安:

bash$ false
bash$ true | echo $?
0
bash$ ksh
ksh$ false
ksh$ true | echo $?
0
ksh$ zsh
zsh$ false
zsh$ true | echo $?
1

直观地看,zsh 做对了,而 bash 和 ksh 错了。 是“最近执行的管道的退出状态”,在每种情况下都应为 1。请注意,在 和 中也打印 0。标准在这一点上是灵活的(即,行为是未指定的),还是在这里是不合规的?我也很想知道 bash 和 ksh 在做什么来弄错这一点。$?false | echo $?kshbashbashksh

$ bash --version
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin11)
Copyright (C) 2007 Free Software Foundation, Inc.
$ zsh --version
zsh 4.3.11 (i386-apple-darwin11.0)
$ ksh --version
  version         sh (AT&T Research) 1993-12-28 s+
bash shell sh zsh ksh

评论

2赞 lurker 4/18/2015
当我运行你的示例时,我得到了 ,而不是 .bash10
0赞 Mat 4/18/2015
什么版本的 bash?生成与我的系统上的 zsh 输出相同的结果。
0赞 Manoj Awasthi 4/18/2015
请为所有人提及 shell 的版本。和我一起居然回来了.因此无法验证。zsh0
0赞 Mat 4/18/2015
那是你那里的一个古老的贝壳收藏品......看起来更像一个博物馆:-)
0赞 cypheon 4/18/2015
在 FreeBSD 10.1 上, 行为类似于您的示例 ( 打印 “1”)。在 中,始终打印“0”。/bin/shzshechocsh... | echo $?

答:

4赞 hek2mgl 4/18/2015 #1

POSIX 说道:

$? 扩展到最新 [命令或] 管道的十进制退出状态...

请注意@lurker的评论。当前版本中的 Bash 的行为与 相同。4.3.11zsh

在管道中发生的事情将由管道之前的命令设置,并且在管道内不会更改。这就是为什么预期的结果是 -> 的返回值。这就是POSIX所规定的。bashzsh$?false1

我找不到任何描述该行为的文档。我只能假设在执行管道之前重置,因为以下代码有效:kshksh$?

#!/bin/ksh
false
ret=$?
true | echo "$ret"

可能这应该作为错误提交到 .但是,我不确定POSIX是否完全指定了这种行为。ksh

评论

2赞 William Pursell 4/18/2015
是的,所以在每种情况下都应该是 返回的状态。它应该引用最新的管道,并且使用它的管道的建设应该是无关紧要的。$?false
0赞 4/18/2015
@hek2mgl 嗯?如何扩展到退出状态?它在运行之前进行评估。当然,之后,将设置为退出状态(通常为零),但这不是问题所在,不是吗?$?echo $?echoechoechoecho