Die Shell-Warnung zu function beheben: POSIX sh und Bash
In einem Skript mit #!/bin/sh wird eine Funktion als hello() { ...; } ohne das Schlüsselwort function deklariert. Benötigt das Skript Bash-Syntax, muss Bash gewählt und entsprechend aufgerufen werden. Ein Aufruf mit sh script.sh richtet sich nicht nach einer Bash-Shebang in der Datei.
ShellCheck SC2112 erläutert, dass function keine POSIX-sh-Syntax ist. Dass eine bestimmte /bin/sh-Implementierung sie akzeptiert, belegt keine Portabilität.
Ablauf
Der aufgerufene Interpreter parst die Funktion. Das Beispiel prüft, ob genau ein Argument vorliegt, und erhält Leerzeichen und Platzhalterzeichen durch Anführungszeichen.
Eine Funktion für die gewählte Shell schreiben
Als greet.sh speichern. Die Anführungszeichen in "$1" und "$@" erhalten Leerzeichen und Platzhalterzeichen in Argumenten.
greet.sh
#!/bin/sh
set -eu
greet() {
if [ "$#" -ne 1 ]; then
printf '%s\n' 'usage: greet.sh NAME' >&2
return 2
fi
printf 'Hello, %s\n' "$1"
}
greet "$@"
sh -n greet.sh
sh greet.sh 'Ada Lovelace'
sh greet.sh 'Ada *'
Die Ausgaben sind Hello, Ada Lovelace und Hello, Ada *. sh -n prüft nur die Syntax; das Skript muss deshalb auch ausgeführt werden. Fehlende oder überzählige Argumente führen zu einem Nutzungshinweis auf stderr und zum Exitstatus 2. Bei einem gültigen Argument ist der Status 0.
Shebang und ausdrücklich aufgerufenen Interpreter unterscheiden
| Aufruf | Wahl des Interpreters |
|---|---|
sh greet.sh NAME |
Das aufgerufene sh liest die Datei. |
bash greet.sh NAME |
Bash liest die Datei. |
chmod +x greet.sh, dann ./greet.sh NAME |
Bei dieser Ausführung gilt die Shebang der Datei. |
Für Bash-Arrays oder [[ ... ]] wird #!/usr/bin/env bash verwendet und das Skript mit bash script.sh oder als ausführbare Datei ./script.sh gestartet. Bei sh script.sh darf keine Bash-Syntax vorausgesetzt werden. Siehe ShellChecks Erklärung zur Shell-Auswahl.
return einer Funktion gibt die Kontrolle und einen Status an den Aufrufer zurück. exit beendet die laufende Shell. Hier ist der Funktionsaufruf das letzte Kommando, daher wird sein Status zum Exitstatus des Skripts.
Das Beispiel wurde mit Argumenten mit Leerzeichen und Platzhalterzeichen sowie ungültigen Argumentanzahlen geprüft. /bin/sh-Implementierungen unterscheiden sich; deshalb auch auf der Shell des Zielsystems testen. Als nächsten Automatisierungsschritt bieten sich der numerische Versionsvergleich oder die GitHub-Release-Abfrage an, bei denen Eingaben und Fehlerstatus ebenfalls wichtig sind.
Diskussion