web-dev-qa-db-fra.com

différence entre "fonction foo () {}" et "foo () {}"

Je peux définir les fonctions bash en utilisant ou en omettant le mot clé function. Y a-t-il une différence?

#!/bin/bash

function foo() {
  echo "foo"
}

bar() {
  echo "bar"
}

foo

bar

Les deux appels aux fonctions foo et bar réussissent et je ne vois aucune différence. Je me demande donc si c'est juste pour améliorer la lisibilité, ou s'il y a quelque chose qui me manque ...

BTW dans d'autres shells comme dash (/bin/sh est lié à dash dans debian/ubuntu), il échoue lors de l'utilisation du mot clé function.

103
Carlos Campderrós

Il n'y a pas de différence AFAIK, à part le fait que la deuxième version est plus portable.

44
schaiba

Le mot clé function a été introduit dans ksh . Le traditionnel Bourne Shell n'avait que la syntaxe foo (), et POSIX standardise uniquement la foo () syntaxe.

Dans ATT ksh (mais pas pdksh), il existe quelques différences entre les fonctions définies par function et les fonctions définies avec la syntaxe Bourne/POSIX. Dans les fonctions définies par function, le mot clé typeset déclare une variable locale: une fois la fonction terminée, la valeur de la variable est réinitialisée à ce qu'elle était avant d'entrer dans la fonction. Avec la syntaxe classique, les variables ont une portée globale, que vous utilisiez typeset ou non.

$ 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

Une autre différence dans ksh est que les fonctions définies avec le mot clé function ont leur propre contexte d'interruption. Les interruptions définies en dehors de la fonction sont ignorées lors de l'exécution de la fonction, et les erreurs fatales à l'intérieur de la fonction ne quittent que la fonction et non du script entier. De plus, $0 Est le nom de la fonction dans une fonction définie par function mais le nom du script dans une fonction définie avec ().

Pdksh n'émule pas ATT ksh. Dans pdksh, typeset crée des variables de portée locale quelle que soit la fonction, et il n'y a pas d'interruptions locales (bien que l'utilisation de function fasse quelques différences mineures - voir la page de manuel pour plus de détails).

Bash et zsh ont introduit le mot clé function pour la compatibilité avec ksh. Cependant, dans ces shells, function foo { … } Et foo () { … } sont strictement identiques, tout comme les extensions bash et zsh function foo () { … }. Le mot clé typeset déclare toujours des variables locales (sauf avec -g Bien sûr), et les traps ne sont pas locaux (vous pouvez obtenir des traps locaux dans zsh en définissant l'option local_traps).

foo() any-command

est la syntaxe Bourne prise en charge par tout shell de type Bourne mais bash, yash et les versions récentes de posh (qui ne prennent en charge que les commandes composées). (les implémentations Bourne Shell et AT&T de ksh ne supportent pas foo() any-command > redirections sauf si any-command est une commande composée).

foo() any-compound-command

(exemples de commandes composées: { cmd; }, for i do echo "$i"; done, (cmd) ... la plus utilisée étant { ...; })

est la syntaxe POSIX prise en charge par tout shell de type Bourne et celle que vous souhaitez généralement utiliser.

function foo { ...; }

est la syntaxe Korn Shell, antérieure à la syntaxe Bourne. N'utilisez celui-ci que si vous écrivez spécifiquement pour la mise en œuvre AT&T de Korn Shell et avez besoin du traitement spécifique qu'il y reçoit. Cette syntaxe n'est pas POSIX, mais est prise en charge par bash, yash et zsh pour la compatibilité avec le shell Korn à travers ces shells (et la base basée sur pdksh variantes du Korn Shell) ne le traitent pas différemment de la syntaxe standard.

function foo () { ...; }

est la syntaxe de no Shell et ne doit pas être utilisé . Il est uniquement pris en charge par accident par bash, yash, zsh et les variantes basées sur pdksh du Korn Shell. Soit dit en passant, c'est aussi la syntaxe de la fonction awk.

Si nous continuons à descendre la liste ésotérique,

function foo() other-compound-command

(comme function foo() (subshell) ou function foo() for i do; ... done) est encore pire. Il est supporté par bash, yash et zsh, mais pas ksh, même les variantes basées sur pdksh.

Tandis que:

function foo() simple command

est uniquement pris en charge par zsh.

35
Stéphane Chazelas

Sémantiquement, ces deux formes sont équivalentes dans Bash.

Depuis la page de manuel:

Les fonctions du shell sont déclarées comme suit:

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

Ceci définit une fonction nommée name. Le mot réservé fonction est facultatif. Si la fonction mot réservé est fourni, les parenthèses sont facultatives.

EDIT: Je viens de remarquer que cette question est balisée posix. Dans POSIX sh, le mot clé function n'est pas utilisé (bien qu'il soit réservé).

22
depquid

Plusieurs autres ont répondu correctement maintenant, mais voici mon résumé concis:

La deuxième version est portable et est susceptible de fonctionner avec de nombreux shells standard (en particulier POSIX).

La première version ne fonctionnera qu'avec bash, mais vous pouvez omettre les parenthèses après le nom de la fonction.

Sinon, ils représentent des entités identiques après que bash les ait interprétés.

3
destenson