
Ich habe ein einfaches Skript mit einer for
Schleife von Bash, das ich in Zsh zum Laufen bringen möchte. Ich war davon ausgegangen, dass der Shebang sicherstellen würde, dass eine POSIX-kompatible Shell verwendet wird (auf meinem System habe ich das /bin/sh -> dash*
), sodass es keine Probleme geben würde.
MWE-Skript, wobei es ITEMS
sich tatsächlich um die Ausgabe eines Befehls handelt, der Pakete auflistet, z. B 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
Dies ist die Ausgabe, wenn ich versuche, das Skript in folgendem Format auszuführen 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
Wenn ich es in einem Bash-Terminal ausführe, funktioniert es einwandfrei. Ich glaube, ich habe missverstanden, wie der Shebang von interpretiert wird zsh
? Kann mir bitte jemand erklären, wie es verwendet werden soll, sodass ich beim Ausführen von source scratch.sh
oder . ./scratch.sh
dieselbe Ausgabe erhalte, als hätte ich ausgeführt sh scratch.sh
? Ich weiß, dass ich mein For-Loop-Skript so ändern könnte, dass es nativ mit zsh
und kompatibel ist bash
, aber ich möchte verwenden, /bin/sh -> dash
damit ich immer eine POSIX-kompatible Shell verwende und mir keine Gedanken über Bashismen oder Zshismen machen muss.
Entschuldigen Sie, wenn dies eine einfache Frage ist. Ich habe nach und Shebang gesucht zsh
, posix
aber keine ähnliche Frage gefunden.
Antwort1
Der Shebang hat nur dann eine Auswirkung, wenn Sie das Skript direkt ausführenohne anzugeben, wie es ausgeführt werden soll; das heißt, mit etwas wie ./scratch.sh
oder /path/to/scratch.sh
oder indem Sie es in ein Verzeichnis in Ihrem Verzeichnis legen PATH
und einfach verwenden scratch.sh
.
Wenn Sie es mit einem anderen Befehl ausführen, steuert dieser, was damit geschieht (Überschreiben des Shebang). Wenn Sie verwenden bash scratch.sh
, läuft es in bash
; wenn Sie verwenden zsh scratch.sh
, läuft es in zsh
; wenn Sie verwenden sh
, läuft es in dem, sh
was sich auf Ihrem System befindet ( dash
in Ihrem speziellen Fall).
Wenn Sie source scratch.sh
oder verwenden . scratch.sh
, wird es in ausgeführtdie aktuelle Shell, was auch immer das ist. Das ist der ganze Zweck der .
und source
Befehle. Und auch hier wird der ganze Kram ignoriert.
Antwort2
Das geht nicht. . script
oder source script
einfach einschließt script
, wird dafür keine separate Standard- oder Nicht-Standard-Shell erstellt. Was Shebangs betrifft, für zsh
(wenn SieQuelleein Skript stattausführenes) es sind nur Kommentare.
Sie können zsh
jedoch anweisen, vorübergehend eine Standard-Shell zu emulieren (oder dies zu versuchen). Ihre Abweichung kann abweichen.
emulate sh -c '. ./scratch.sh'
emulate which_sh -c str
str
wird mit der angegebenen, vorübergehend wirksamen Emulation ausgewertet und, was noch wichtiger ist, wird dafür sorgen, dass es an allen während der Auswertung von definierten Funktionen „klebt“ str
, wodurch der Emulationsmodus während ihrer Ausführung automatisch aktiviert wird.