it-swarm.com.de

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

Ich kann bash Funktionen definieren, indem ich das Schlüsselwort function verwende oder weglasse. Gibt es einen Unterschied?

#!/bin/bash

function foo() {
  echo "foo"
}

bar() {
  echo "bar"
}

foo

bar

Beide Aufrufe der Funktionen foo und bar sind erfolgreich und ich kann keinen Unterschied feststellen. Ich frage mich also, ob es nur darum geht, die Lesbarkeit zu verbessern, oder ob mir etwas fehlt ...

Übrigens in anderen Shells wie dash (/bin/sh ist in debian/ubuntu mit dash verknüpft) schlägt fehl, wenn das Schlüsselwort function verwendet wird.

103

Es gibt keinen Unterschied AFAIK, außer der Tatsache, dass die zweite Version portabler ist.

44
schaiba

Das Schlüsselwort function wurde in ksh eingeführt. Die traditionelle Bourne Shell hatte nur die Syntax foo () und POSIX standardisiert nur die foo () Syntax.

In ATT ksh (aber nicht pdksh) gibt es einige Unterschiede zwischen Funktionen, die durch function definiert sind, und Funktionen, die mit der Bourne/POSIX-Syntax definiert wurden. In Funktionen, die durch function definiert sind, deklariert das Schlüsselwort typeset eine lokale Variable: Sobald die Funktion beendet wird, wird der Wert der Variablen auf den Wert vor dem Aufrufen der Funktion zurückgesetzt. Mit der klassischen Syntax haben Variablen einen globalen Bereich, unabhängig davon, ob Sie typeset verwenden 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 Funktionen, die mit dem Schlüsselwort function definiert wurden, einen 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 ist $0 Der Funktionsname in einer durch function definierten Funktion, aber der Skriptname in einer mit () Definierten Funktion.

Pdksh emuliert ATT ksh nicht. In pdksh erstellt typeset unabhängig von der Funktion Variablen mit lokalem Gültigkeitsbereich, und es gibt keine lokalen Traps (obwohl die Verwendung von function einige geringfügige Unterschiede bewirkt - Einzelheiten finden Sie in der Manpage).

Bash und zsh haben das Schlüsselwort function eingeführt, um die Kompatibilität mit ksh zu gewährleisten. In diesen Shells sind function foo { … } Und foo () { … } jedoch genau identisch, ebenso wie die bash- und zsh-Erweiterung function foo () { … }. Das Schlüsselwort typeset deklariert immer lokale Variablen (außer natürlich mit -g), Und Traps sind nicht lokal (Sie können lokale Traps in zsh erhalten, indem Sie die Option local_traps Setzen).

foo() any-command

ist die Bourne-Syntax, die von jeder Bourne-ähnlichen Shell unterstützt wird, außer bash, yash und neueren Versionen von posh (die nur zusammengesetzte Befehle unterstützen). (Die Bourne Shell- und AT & T-Implementierungen von ksh unterstützen foo() any-command > redirections nur, wenn any-command ein zusammengesetzter Befehl ist.).

foo() any-compound-command

(Beispiele für zusammengesetzte Befehle: { cmd; }, for i do echo "$i"; done, (cmd) ... am häufigsten verwendet wird { ...; })

ist die POSIX-Syntax, die von jeder Bourne-ähnlichen Shell unterstützt wird und die Sie normalerweise verwenden möchten.

function foo { ...; }

ist die Korn Shell-Syntax, die vor der Bourne-Syntax liegt. Verwenden Sie diese nur, wenn Sie speziell für die AT & T-Implementierung der Korn-Shell schreiben und die spezifische Behandlung benötigen, die sie dort erhält. Diese Syntax ist nicht POSIX, sondern wird von bash, yash und zsh unterstützt, um die Kompatibilität mit der Korn-Shell über diese Shells (und die auf pdksh basierenden) zu gewährleisten Varianten der Korn Shell) behandeln sie nicht anders als die Standardsyntax.

function foo () { ...; }

ist die Syntax von no Shell und sollte nicht verwendet werden . Es wird nur zufällig von bash, yash, zsh und den pdksh basierten Varianten der Korn Shell unterstützt. Übrigens ist es auch die Funktionssyntax awk.

Wenn wir die esoterische Liste weiter durchgehen,

function foo() other-compound-command

(wie function foo() (subshell) oder function foo() for i do; ... done) ist noch schlimmer. Es wird von bash, yash und zsh unterstützt, aber nicht von ksh, selbst den auf pdksh basierenden Varianten.

Während:

function foo() simple command

wird nur von zsh unterstützt.

35

Semantisch sind diese beiden Formen in Bash äquivalent.

Von der Manpage:

Shell-Funktionen werden wie folgt deklariert:

name () compound-command [redirection]
function name [()] compound-command [redirection]

Dies definiert eine Funktion namens name. Das reservierte Wort Funktion ist optional. Wenn das reservierte Wort Funktion angegeben wird, sind die Klammern optional.

EDIT: Ich habe gerade bemerkt, dass diese Frage mit posix markiert ist. In POSIX sh wird das Schlüsselwort function nicht verwendet (obwohl es reserviert ist).

22
depquid

Einige andere haben inzwischen richtig geantwortet, aber hier ist meine kurze Zusammenfassung:

Die zweite Version ist portabel und funktioniert wahrscheinlich mit vielen Standard-Shells (insbesondere POSIX).

Die erste Version funktioniert nur mit Bash, aber Sie können die Klammern nach dem Funktionsnamen weglassen.

Andernfalls stellen sie identische Entitäten dar, nachdem Bash sie interpretiert hat.

3
destenson