Отвечаяэтот вопросЯ обнаружил очень забавную (и тонкую) разницу между поведением в 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] %
здесь каталог изменен.
Кажется, что &
in bash
имеет другой приоритет, чем in zsh
--- Я имею в виду, что команда, похоже, читается как
(cd /tmp && echo A) &
в bash
и как
cd /tmp && (echo A &)
в zsh
. Это правильно или причина различного поведения в чем-то другом?
решение1
Различное, документированное поведение вzshmisc
Список — это последовательность из нуля или более подсписков, в которой каждый подсписок завершается
;
,&
,&|
,&!
или новой строкой. Этот терминатор может быть необязательно опущен в последнем подсписке в списке, когда список отображается как сложная команда внутри(...)
или{...}
. Когда подсписок завершается;
или новой строкой, оболочка ждет его завершения, прежде чем выполнять следующий подсписок. Если подсписок завершается&
,&|
, или&!
, оболочка выполняет последний конвейер в нем в фоновом режиме и не ждет его завершения (обратите внимание на отличие от других оболочек, которые выполняют весь подсписок в фоновом режиме). Фоновый конвейер возвращает статус ноль.
решение2
В нем зарыта zshmisc(1)
следующая строка:
Если подсписок завершается символом
&',
&|' или `&!', оболочка выполняет последний конвейер в нем в фоновом режиме,
Хотя в нем конкретно не указано, что другие конвейеры в подсписке выполняются в текущей оболочке, похоже, именно это и подразумевается, и наблюдаемое вами поведение подтверждает эту интерпретацию. Например:
$ echo $foo $bar
$ foo=3 && bar=5 && sleep 1 &
$ echo $foo $bar
3 5
также поддерживается идея о том, что первые два конвейера выполняются в текущей оболочке, и только последний конвейер подсписка фактически выполняется в фоновом режиме.