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サブシェルで実行されるため、現在のディレクトリは変更されません。

ありませんで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] % 

ここでディレクトリが変更されます。

&の優先順位は、のbash優先順位と異なるようですzsh。つまり、コマンドは次のように読み取られるようです。

(cd /tmp && echo A) & 

bash、そしてとして

cd /tmp && (echo A &) 

zsh。これは正しいですか、それとも異なる動作の原因は別のものですか?

答え1

異なる、文書化された行動zshmisc

リストは 0 個以上のサブリストのシーケンスであり、各サブリストは 、 、 、 、または改行で終了します;&リスト&|&!または 内の複合コマンドとして表示される場合、このターミネータは、リストの最後のサブリストから省略できます(...){...}サブリストが または 改行で終了する場合;、シェルはそれが終了するまで待ってから次のサブリストを実行します。サブリストが&&|、またはで終了する場合&!、シェルは最後のパイプラインをバックグラウンドで実行し、それが終了するまで待ちません (サブリスト全体をバックグラウンドで実行する他のシェルとの違いに注意してください)。バックグラウンドのパイプラインは、ステータス 0 を返します。

答え2

zshmisc(1)そこには次の行が埋め込まれています。

サブリストが&',「&|」または「&!」で終了する場合、シェルはバックグラウンドで最後のパイプラインを実行します。

サブリスト内の他のパイプラインが現在のシェルで実行されるとは具体的には述べられていませんが、それが暗示されているように思われ、観察された動作はその解釈を裏付けています。例:

$ echo $foo $bar

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

また、最初の 2 つのパイプラインは現在のシェルで実行され、サブリストの最後のパイプラインのみが実際にバックグラウンドで実行されるという概念もサポートしています。

関連情報