PIPESTATUS忽略了否定?

时间:2016-04-06 09:15:17

标签: bash shell negation exitstatus pipestatus

我刚刚在bash(版本4.2.25(1)-release)中找到了以下结果:

$ true; echo "${PIPESTATUS[@]}"
0
$ ! true; echo "${PIPESTATUS[@]}"
0
$ false; echo "${PIPESTATUS[@]}"
1
$ ! false; echo "${PIPESTATUS[@]}"
1
$ true && false; echo "${PIPESTATUS[@]}"
1
$ true && ! false; echo "${PIPESTATUS[@]}"
1

因此,$PIPESTATUS似乎忽略了所有情况下的否定。这是一个已知的问题?我找不到任何关于它的东西。或者这是一个想要的行为?如果是这样,背后的原因是什么?

使用子shell时,一切都按照我的预期运行:

$ (true && ! false); echo "${PIPESTATUS[@]}"
0

2 个答案:

答案 0 :(得分:3)

我认为这种行为意图,如果用完整的管道进行查看会变得更加清晰:

a | b | c | d ; echo "${PIPESTATUS[@]}"

这将显示流程abcd的退出状态。

现在,否定仅适用于完整管道的退出状态:

! a | b | c | d ; echo "${PIPESTATUS[@]}"

不允许否定部分管道:

a | ! b | c | d   # Syntax error at "| !"

由于这种方法,管道关联强于否定(可以说在关联级别上这是! (a | b | c | d)),因此管道成分的结果不受否定的影响,因为否定在评估管道后,稍后应用。

答案 1 :(得分:2)

shell&和

! a | b | c被解释为!{a | b | c;}。不是{! a;} | b | c

单个命令退出状态存储在${PIPESTATUS[@]}

$?指整个命令的退出状态,包括!

您可以通过实际生成子shell来强制(! a) | b | c。 e.g。

$ true; echo "${PIPESTATUS[@]}"
0
$ (! true); echo "${PIPESTATUS[@]}"
1
$ false; echo "${PIPESTATUS[@]}"
1
$ (! false); echo "${PIPESTATUS[@]}"
0