bash 和 zsh 中 && 与 & 的优先级

bash 和 zsh 中 && 与 & 的优先级

正在接听这个问题bash我发现和中的行为之间有一个非常有趣(且微妙)的差异zsh

bash

romano@RRyS:~$ pwd
/home/romano
romano@RRyS:~$ alias x="cd /bin && ./echo A >/dev/null  &"
romano@RRyS:~$ x
[1] 16611
romano@RRyS:~$ pwd
/home/romano

正如您所看到的,alias 的执行x是在子 shell 中执行的,因此当前目录不会改变。

不在zsh

[romano:~] % pwd
/home/romano
[romano:~] % alias x="cd /bin && ./echo A >/dev/null &"
[romano:~] % x
[1] 16744
[1]  + 16744 done       ./echo A >/dev/null                                    
1& [romano:/bin] % pwd
/bin
[romano:/bin] % 

此处目录已更改。

看来&in 的bash优先级与 in 不同zsh--- 我的意思是,该命令似乎被读作

(cd /tmp && echo A) & 

bash和作为

cd /tmp && (echo A &) 

zsh。这是正确的还是造成不同行为的原因是另一个?

答案1

不同的、有记录的行为zshmisc

;列表是零个或多个子列表的序列,其中每个子列表以、&&|&!或换行符终止。当列表作为复杂命令出现在(...)或中时,可以选择从列表中的最后一个子列表中省略该终止符{...}。当子列表由 或 换行符终止时;,shell 会等待它完成,然后再执行下一个子列表。如果子列表以&&|或终止&!,则 shell 会在后台执行其中的最后一个管道,并且不会等待它完成(请注意与在后台执行整个子列表的其他 shell 的区别)。后台管道返回零状态。

答案2

埋藏的zshmisc(1)是以下行:

如果子列表以 &|' 或 `&!' 终止&',,则 shell 在后台执行其中的最后一个管道,

虽然它没有具体说明子列表中的其他管道在当前 shell 中执行,但这似乎确实是它所暗示的,并且您观察到的行为支持该解释。例如:

$ echo $foo $bar

$ foo=3 && bar=5 && sleep 1 &
$ echo $foo $bar
3 5

还支持这样的概念:前两个管道在当前 shell 中执行,并且只有子列表的最后一个管道实际上在后台执行。

相关内容