Unterschied zwischen "function foo() {}" und "foo() {}"

Unterschied zwischen "function foo() {}" und "foo() {}"

Ich kann bashFunktionen definieren, indem ich das functionSchlüsselwort verwende oder weglasse. Gibt es da einen Unterschied?

#!/bin/bash

function foo() {
  echo "foo"
}

bar() {
  echo "bar"
}

foo

bar

Beide Funktionsaufrufe foosind barerfolgreich 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/shist dashin Debian/Ubuntu ein symbolischer Link dazu) bei Verwendung des functionSchlüsselworts fehl.

Antwort1

Der Grund für die beiden unterschiedlichen Syntaxen ist historisch. Das functionSchlü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, functionund Funktionen, die mit der Bourne/POSIX-Syntax definiert sind. In Funktionen, die durch definiert sind function, deklariert das typesetSchlü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 typesetoder 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 functionSchlü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 $0ist der Funktionsname in einer durch definierten Funktion, functionaber der Skriptname in einer mit definierten Funktion ().

Pdksh emuliert ATT ksh nicht. In pdksh typesetwerden lokal gültige Variablen unabhängig von der Funktion erstellt und es gibt keine lokalen Traps (obwohl die Verwendung functioneinige geringfügige Unterschiede mit sich bringt – Einzelheiten finden Sie auf der Manpage).

Bash und zsh haben das functionSchlü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 typesetSchlüsselwort deklariert immer lokale Variablen (außer -gnatürlich mit) und Traps sind nicht lokal (Sie können lokale Traps in zsh erhalten, indem Sie die local_trapsOption 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, aberyashund aktuelle Versionen von posh(die nur zusammengesetzte Befehle unterstützen). (Die Bourne-Shell und die AT&T-Implementierungen von unterstützen jedoch kshnicht , es sei denn, es handelt sich um einen zusammengesetzten Befehl.)foo() any-command > redirectionsany-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 bashdient 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.yashzshpdksh

function foo () { ...; }

ist die Syntax vonNEINSchale undsollte nicht benutzt werdenbash. Es wird nur zufällig von , yash, zshund den pdkshbasierten Varianten der Korn-Shell unterstützt . Übrigens ist es auch die awkFunktionssyntax.

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, yashund 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 zshebenfalls 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.

verwandte Informationen