Emr*_* He 4 shell pipeline echo
我意识到这个事实,但我不知道为什么:
cat abc | echo $?
Run Code Online (Sandbox Code Playgroud)
如果abc不存在,但上面的命令仍然返回0.有谁知道关于为什么的理论?
小智 10
它必须是这种方式的原因是管道由同时运行的进程组成.cat退出代码不能echo作为参数传递,因为参数在命令开始运行时设置,并echo在cat完成之前开始运行.
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)
它与 没有任何关系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)