
У меня есть простой скрипт, включающий for
цикл из bash, который я пытаюсь заставить работать в zsh. Я предполагал, что shebang обеспечит использование оболочки, совместимой с POSIX (в моей системе это так /bin/sh -> dash*
), поэтому не возникнет никаких проблем.
Скрипт MWE, где ITEMS
на самом деле находится вывод команды, которая выводит список пакетов, например ITEMS=$(pip freeze)
:
#!/bin/sh
# ITEMS=$(pip freeze) # Example of useful command
ITEMS="Item1
Item2
Item3" # Dummy variable for testing
for ITEM in $ITEMS; do
echo $ITEM
echo Complete
done
Вот вывод, когда я пытаюсь запустить скрипт zsh
:
$ source scratch.sh
Item1
Item2
Item3
Complete # Undesired
$ . ./scratch.sh
Item1
Item2
Item3
Complete # Undesired
$ bash scratch.sh
Item1
Complete
Item2
Complete
Item3
Complete # Desired
$ sh scratch.sh
Item1
Complete
Item2
Complete
Item3
Complete # Desired
Когда я запускаю его в терминале bash, он работает нормально. Я думаю, я неправильно понял, как интерпретируется shebang zsh
? Может кто-нибудь объяснить мне, как его следует использовать, чтобы при запуске source scratch.sh
или . ./scratch.sh
у меня был тот же вывод, что и при запуске sh scratch.sh
? Я знаю, что могу изменить свой сценарий цикла for, чтобы он был совместим с zsh
и bash
изначально, но я хочу использовать /bin/sh -> dash
поэтому я всегда использую оболочку, совместимую с posix, и не беспокоиться о bashisms или zshisms.
Извините, если это простой вопрос, я искал и всё такое zsh
, posix
но не нашёл похожего вопроса.
решение1
Шебэнг имеет эффект только если вы выполняете скрипт напрямуюбез указания того, как его запустить; то есть, с помощью чего-то вроде ./scratch.sh
или /path/to/scratch.sh
, или поместив его в каталог в вашем PATH
и просто используя scratch.sh
.
Если вы запускаете его с помощью какой-то другой команды, это контролирует, что с ним делается (переопределяя shebang). Если вы используете bash scratch.sh
, он запускается в bash
; если вы используете zsh scratch.sh
, он запускается в zsh
; если вы используете sh
, он запускается в том, что sh
есть в вашей системе ( dash
в вашем конкретном случае).
Если вы используете source scratch.sh
или. scratch.sh
, он запускается втекущая оболочка, что бы это ни было. Вот и вся цель команд .
и source
. И снова, шебанг здесь игнорируется.
решение2
Вы не можете этого сделать. . script
или source script
просто включает script
, он не создает отдельную стандартную или нестандартную оболочку, чтобы сделать это. Что касается shebangs, дляzsh
(когда выисточниксценарий, а невыполнятьэто просто комментарии.
Однако вы можете дать команду zsh
(попытаться) временно эмулировать стандартную оболочку. YMMV.
emulate sh -c '. ./scratch.sh'
emulate which_sh -c str
будет выполнять оценку str
с временно включенной указанной эмуляцией и, что более важно, заставит ее «прилипнуть» ко всем функциям, определенным во время оценки str
, в результате чего режим эмуляции будет автоматически включаться во время их выполнения.