2

我刚刚在 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似乎在所有情况下都忽略了否定。这是一个已知的问题?我找不到任何关于它的信息。或者这是一种通缉行为?如果是这样,其背后的原因是什么?

使用 subshel​​l 时,一切正常:

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

2 回答 2

3

我认为这种行为是有意的,并且如果从完整的管道中查看会变得更加清晰:

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

这将显示进程abc和的退出状态d

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

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

不允许否定部分管道:

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

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

于 2016-04-06T09:47:05.327 回答
2

! a | b | c被 shell 解释为!{a | b | c;}而不是{! a;} | b | c.

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

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

(! a) | b | c您可以通过实际生成子外壳来强制。例如

$ true; echo "${PIPESTATUS[@]}"
0
$ (! true); echo "${PIPESTATUS[@]}"
1
$ false; echo "${PIPESTATUS[@]}"
1
$ (! false); echo "${PIPESTATUS[@]}"
0
于 2016-04-06T09:48:08.353 回答