%20%7B%7D%22%20und%20%22foo()%20%7B%7D%22.png)
Ich kann bash
Funktionen definieren, indem ich das function
Schlüsselwort verwende oder weglasse. Gibt es da einen Unterschied?
#!/bin/bash
function foo() {
echo "foo"
}
bar() {
echo "bar"
}
foo
bar
Beide Funktionsaufrufe foo
sind bar
erfolgreich und ich kann keinen Unterschied erkennen. Ich frage mich also, ob es nur der besseren Lesbarkeit dient oder ob ich etwas übersehen habe ...
Übrigens schlägt es in anderen Shells wie dash
( /bin/sh
ist dash
in Debian/Ubuntu ein symbolischer Link dazu) bei Verwendung des function
Schlüsselworts fehl.
Antwort1
Der Grund für die beiden unterschiedlichen Syntaxen ist historisch. Das function
Schlüsselwort stammt auskshDie C-inspirierte ()
Syntax stammt aus demBourne-Shell.POSIXstandardisiert nur die Bourne foo ()
-Syntax. Bash und zsh unterstützen beide, sowie den Hybrid function foo () { … }
. Außer in ATT ksh ist die resultierende Funktion genau dieselbe.
Achten Sie auf eine Syntaxfalle ()
: Der Funktionsname unterliegt einer Aliaserweiterung.
alias f=g
f () { echo foo; }
type f # f is an alias for g
type g # g is a shell function
f # alias f → function g → print foo
\f # no alias lookup → f: not found
g # function g
In ATT ksh (aber nicht pdksh und seinen Nachkommen wie mksh) gibt es einige Unterschiede zwischen Funktionen, die durch definiert sind, function
und Funktionen, die mit der Bourne/POSIX-Syntax definiert sind. In Funktionen, die durch definiert sind function
, deklariert das typeset
Schlüsselwort eine lokale Variable: Sobald die Funktion beendet wird, wird der Wert der Variablen auf den Wert vor dem Aufruf der Funktion zurückgesetzt. Mit der klassischen Syntax haben Variablen einen globalen Gültigkeitsbereich, unabhängig davon, ob Sie sie verwenden typeset
oder nicht.
$ ksh -c 'a=global; f () { typeset a=local; }; f; echo $a'
local
$ ksh -c 'a=global; function f { typeset a=local; }; f; echo $a'
global
Ein weiterer Unterschied in ksh besteht darin, dass mit dem function
Schlüsselwort definierte Funktionen ihren eigenen Trap-Kontext haben. Außerhalb der Funktion definierte Traps werden bei der Ausführung der Funktion ignoriert, und schwerwiegende Fehler innerhalb der Funktion beenden nur die Funktion und nicht das gesamte Skript. Außerdem $0
ist der Funktionsname in einer durch definierten Funktion, function
aber der Skriptname in einer mit definierten Funktion ()
.
Pdksh emuliert ATT ksh nicht. In pdksh typeset
werden lokal gültige Variablen unabhängig von der Funktion erstellt und es gibt keine lokalen Traps (obwohl die Verwendung function
einige geringfügige Unterschiede mit sich bringt – Einzelheiten finden Sie auf der Manpage).
Bash und zsh haben das function
Schlüsselwort aus Kompatibilitätsgründen mit ksh eingeführt. In diesen Shells sind function foo { … }
und jedoch foo () { … }
genau identisch, ebenso wie die Bash- und Zsh-Erweiterung function foo () { … }
(mit Ausnahme einer möglichen Aliaserweiterung beim Parsen der Definition, wie oben erläutert). Das typeset
Schlüsselwort deklariert immer lokale Variablen (außer -g
natürlich mit) und Traps sind nicht lokal (Sie können lokale Traps in zsh erhalten, indem Sie die local_traps
Option festlegen).
Antwort2
Soweit ich weiß, gibt es keinen Unterschied, außer der Tatsache, dass die zweite Version portabler ist.
Antwort3
foo() any-command
ist die Bourne-Syntax, die von jeder Bourne-ähnlichen Shell unterstützt wird bash
, aberyash
und aktuelle Versionen von posh
(die nur zusammengesetzte Befehle unterstützen). (Die Bourne-Shell und die AT&T-Implementierungen von unterstützen jedoch ksh
nicht , es sei denn, es handelt sich um einen zusammengesetzten Befehl.)foo() any-command > redirections
any-command
foo() any-compound-command
(Beispiele für zusammengesetzte Befehle: { cmd; }
, for i do echo "$i"; done
, (cmd)
…, am häufigsten wird verwendet { ...; }
)
ist die POSIX-Syntax, die von jeder Bourne-ähnlichen Shell unterstützt wird und die Sie im Allgemeinen verwenden möchten.
function foo { ...; }
ist die Korn-Shell-Syntax, die der Bourne-Syntax vorausging. Verwenden Sie diese nur, wenn Sie speziell für die AT&T-Implementierung der Korn-Shell schreiben und die dortige spezielle Behandlung benötigen. Diese Syntax ist nicht POSIX, wird aber von unterstützt und bash
dient der Kompatibilität mit der Korn-Shell, obwohl diese Shells (und die auf -basierten Varianten der Korn-Shell) sie nicht anders als die Standardsyntax behandeln.yash
zsh
pdksh
function foo () { ...; }
ist die Syntax vonNEINSchale undsollte nicht benutzt werdenbash
. Es wird nur zufällig von , yash
, zsh
und den pdksh
basierten Varianten der Korn-Shell unterstützt . Übrigens ist es auch die awk
Funktionssyntax.
Wenn wir die esoterische Liste weiter durchgehen,
function foo() other-compound-command
(wie function foo() (subshell)
oder function foo() for i do; ... done
) ist sogar noch schlimmer. Es wird von bash
, yash
und unterstützt zsh
, aber nicht von ksh, nicht einmal von den pdksh
-basierten Varianten.
Während:
function foo() simple command
wird nur unterstützt von zsh
.
foo bar() any-command
Oder auch:
$function_list() any-command
Das gleichzeitige Definieren mehrerer Funktionen wird nur unterstützt vonzsh
function { body; } args
() any-compound-command args
Welche sindanonyme FunktionAufrufe werden zsh
ebenfalls nur von unterstützt.
Antwort4
Mehrere andere haben inzwischen richtig geantwortet, aber hier ist meine knappe Zusammenfassung:
Die zweite Version ist portabel und funktioniert wahrscheinlich mit vielen Standard-Shells (insbesondere POSIX-Shells).
Die erste Version funktioniert nur mit Bash, aber Sie können dabei die Klammern nach dem Funktionsnamen weglassen.
Andernfalls stellen sie nach der Interpretation durch Bash identische Entitäten dar.