Учитывает ли zsh shebang bin/sh, чтобы можно было использовать dash?

Учитывает ли zsh shebang bin/sh, чтобы можно было использовать dash?

У меня есть простой скрипт, включающий 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, в результате чего режим эмуляции будет автоматически включаться во время их выполнения.

Связанный контент