【问题标题】:What is the correct value of `$?` in a pipeline?`$?` 在管道中的正确值是多少?
【发布时间】:2015-06-25 09:04:47
【问题描述】:

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

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。请注意,false | echo $?kshbash 中也打印 0。标准在这一点上是否灵活(即行为未指定),或者bashksh 在这里不兼容?我也很想知道 bash 和 ksh 做了什么导致这个错误。

$ 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 示例时,我得到的是 1,而不是 0
  • 什么版本的 bash?在我的系统上产生与您的 zsh 输出相同的输出。
  • 请大家提一下shell的版本。和我在一起zsh 实际上返回了0。因此无法验证。
  • 那是你那里收藏的古代贝壳……看起来更像博物馆 :-)
  • 在 FreeBSD 10.1 上,/bin/sh 在您的示例中的行为类似于 zshecho 打印“1”)。在csh 中,... | echo $? 总是打印“0”。

标签: bash shell sh zsh ksh


【解决方案1】:

POSIX 说:

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

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

bashzsh 中发生的情况是$? 将由命令before 设置,并且不会在管道内更改。这就是为什么预期的结果是来自false -> 1 的返回值。这就是 POSIX 指定的内容。

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

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

可能这应该在ksh 中作为错误提交。但是,我不确定 POSIX 是否足够准确地指定此行为。

【讨论】:

  • 是的,所以在每种情况下$? 应该是false 返回的状态。它应该引用最新的管道,并且正在使用它的管道的构造应该是无关紧要的。
  • @hek2mgl 嗯? echo $?中的$?怎么会扩展为echo的退出状态?它在echo 运行之前被评估。当然,之后echo 将设置为echo 的退出状态(通常为零),但这不是问题所在,不是吗?
猜你喜欢
  • 2011-10-21
  • 2020-02-07
  • 1970-01-01
  • 2021-07-29
  • 1970-01-01
  • 2013-11-20
  • 2012-03-07
  • 1970-01-01
  • 2020-08-06
相关资源
最近更新 更多