为什么管道总是返回"0"后回显返回值($?)

Emr*_* He 4 shell pipeline echo

我意识到这个事实,但我不知道为什么:

cat abc | echo $?
Run Code Online (Sandbox Code Playgroud)

如果abc不存在,但上面的命令仍然返回0.有谁知道关于为什么的理论?

小智 10

必须是这种方式的原因是管道由同时运行的进程组成.cat退出代码不能echo作为参数传递,因为参数在命令开始运行时设置,并echocat完成之前开始运行.

echo不从stdin获取输入,因此echo在管道字符的右侧始终是一个错误.

更新:

既然现在很清楚你是在问一个真正的问题,而不仅仅是误解了你看到的东西,我自己也试过了.我从我尝试过的大多数shell(dash,zsh,pdksh,posh和bash 4.2.37)中得到了我认为正确的结果(1),但是从bash 4.1.10和ksh(版本JM 93u + 2012-02)得到0 -29).

我假设版本之间bash行为的变化是故意的,4.1.x行为被认为是一个bug.如果你看起来足够努力,你可能会在更新日志中找到它.关于ksh不知道.

csh和tcsh($status代替$?)也说0,但我打赌没有人关心这个.

邀请具有较大shell集合的人进行测试:

for sh in /bin/sh /bin/ksh /bin/bash /bin/zsh ...insert more shells here...; do
  echo -n "$sh "
  $sh -c 'false;true|echo $?'
done
Run Code Online (Sandbox Code Playgroud)


fed*_*qui 6

它与 没有任何关系cat abc,但与您执行的上一个命令有关。因此,您执行操作时获得的代码cat abc | echo $?会告诉您历史记录中的上一个命令是否成功。

man bash

特殊参数

- 扩展到最近执行的前台管道的退出状态。

所以当你这样做时:

cat abc | echo $?
Run Code Online (Sandbox Code Playgroud)

echo $?的是您之前使用的命令,而不是cat abc

例子

$ cat a
hello
$ echo $?
0

$ cat aldsjfaslkdfj
cat: aldsjfaslkdfj: No such file or directory
$ echo $?
1
Run Code Online (Sandbox Code Playgroud)

所以

$ cat a
$ cat a | echo $?
0

$ cat aldsjfaslkdfj
cat: aldsjfaslkdfj: No such file or directory
$ cat a | echo $?
1
Run Code Online (Sandbox Code Playgroud)