Retour implicite dans les fonctions bash?

Dites que jai une fonction bash comme ceci:

gmx(){ echo "foo"; } 

cette fonction sera implicitement renvoie la valeur de sortie de la commande echo, ou est-il nécessaire dutiliser return?

gmx(){ echo "foo"; return $? } 

Je suppose que la manière bash fonctionne, le statut de sortie de la commande finale de la fonction bash est celui qui est « retourné », mais pas sûr à 100%.

Réponse

return fait un retour explicite depuis une fonction shell ou » dot script « (un script source). Si return nest pas exécuté, un retour implicite est effectué à la fin de la fonction shell ou du script dot.

Si return est exécuté sans paramètre, cela équivaut à renvoyer le statut de sortie de la dernière commande exécutée.

Cest ainsi que return fonctionne dans tous les POSIX shells.

Par exemple,

gmx () { echo "foo" return "$?" } 

équivaut donc à

gmx () { echo "foo" return } 

qui est identique à

gmx () { echo "foo" } 

En général, il est très rare que vous ayez besoin dutiliser $? du tout. Il nest vraiment nécessaire que si vous devez lenregistrer pour une utilisation future, par exemple si vous devez rechercher sa valeur plusieurs fois (auquel cas vous attribueriez sa valeur à une variable et effectuer une série de tests sur cette variable).

Commentaires

  • Un inconvénient de lutilisation de return est celui des fonctions définies comme f() (...; cmd; return), cela empêche loptimisation que font quelques shells dexécuter le cmd dans le même processus que le sous-shell. Avec de nombreux shells, cela signifie également que létat de sortie de la fonction ne ‘ t porte pas linformation que cmd a été tué quand il a (la plupart des shells peuvent de toute façon ‘ récupérer ces informations).
  • Notez quavec pdksh et certains de ses dérivés (comme OpenBSD sh ou posh), vous ‘ avez besoin de return -- "$?" sil y avait un chance que la dernière commande soit une fonction qui a renvoyé un nombre négatif. mksh (également basé sur pdksh) interdit aux fonctions de renvoyer des valeurs négatives.
  • merci, cela aide, je suppose que je ne ‘ t comprendre comment return x fonctionne différemment de exit x … la seule chose que je sais est que return x ne quittera pas le processus en cours.
  • @AlexanderMills Eh bien, cest ‘ que jai dit: return est utilisé pour retourner à partir dune fonction ou dun script dot. exit fait quelque chose de complètement différent (met fin à un processus).
  • Oui, cest logique, je pense que je commence à avoir une meilleure idée de ce sujet

Réponse

De la page de manuel bash(1):

Lorsquelle est exécutée, létat de sortie dune fonction est létat de sortie de la dernière commande exécutée dans le corps.

Commentaires

  • à droite, et un corollaire pourrait être que linstruction de retour nest rien dautre que létat de sortie?
  • Je suppose que return est une commande intégrée – bien que return 1 soit différent de exit 1, etc. donc
  •  » return [n]: Provoque larrêt de lexécution dune fonction et renvoie la valeur spécifiée par n à son appelant. Si n est omis, le statut de retour est celui de la dernière commande exécutée dans le corps de la fonction.  » (ibid) Donc, return force létat de sortie dune fonction à une valeur spécifique si elle est spécifiée.
  • @AlexandwrMills Oui, return et exit sont tous deux intégrés, sauf que return ne peut être utilisé que dans la fonction. Vous pouvez ‘ terminer un script avec return. Létat de sortie est la valeur renvoyée par la commande. return est une commande qui renvoie cette valeur. Ainsi, linstruction de retour  » nest rien de plus que létat de sortie  » nest tout simplement pas tout à fait exact. Lun est une valeur, lautre est la commande plus la valeur.
  • @AlexanderMills, return renvoie de la fonction, exit quitte tout le shell. Il ‘ est exactement le même que dans, disons C avec return vs exit(n), ou return vs sys.exit() en Python.

Réponse

Je « vais juste ajouter quelques notes de prudence aux réponses déjà fournies:

  • Même si return a une signification très particulière pour le shell, dun point de vue syntaxique, il sagit dune commande interne du shell et dune instruction de retour est analysée comme toute autre commande simple. Cela signifie donc que, comme dans largument de toute autre commande, $? sil nest pas entre guillemets, serait soumis à split + glob

    Vous devez donc citer cela $? pour léviter:

    return "$?" 
  • return naccepte généralement aucune option (ksh93 « s accepte les --help, --man, --author … cependant). Le seul argument attendu (facultatif) est le code de retour. La plage des codes de retour acceptés varie du shell au shell, et si une valeur en dehors de 0..255 est correctement reflétée dans

varie également dun shell à lautre. Voir Code de sortie par défaut lorsque le processus est terminé? pour plus de détails à ce sujet.

La plupart des shells acceptent les nombres négatifs (après tout, largument passé à lappel système _exit() / exitgroup() est un int, donc avec des valeurs englobant au moins – 2 31 à 2 31 -1, il est donc logique que les shells acceptent la même plage pour ses fonctions).

La plupart des shells utilisent le waitpid() et co. API pour récupérer cet état de sortie, mais auquel cas, il est tronqué à un nombre compris entre 0 et 255 lorsquil est stocké dans $?. Même en appelant une fonction nimplique pas de générer un processus et utilisé waitpid() pour récupérer son statut de sortie car tout est fait dans le même processus, de nombreux shells imitent également que waitpid() comportement lors de lappel de fonctions. Cela signifie que même si vous appelez return avec une valeur négative, $? contiendra un nombre positif.

Maintenant, parmi les shells dont return accepte les nombres négatifs (ksh88, ksh93, bash, zsh, pdksh et dérivés autres que mksh, yash), il y a quelques ( pdksh et yash) qui en ont besoin sous la forme return -- -123 sinon que -123 est considéré comme trois -1, -2, -3 options non valides.

Comme pdksh et ses de les rivaux (comme OpenBSD sh ou posh) conservent le nombre négatif dans $?, cela signifie que faire return "$?" échouerait lorsque $? contient un nombre négatif (ce qui se produirait lorsque la dernière commande dexécution était une fonction qui retournait un nombre négatif ).

Donc, return -- "$?" serait mieux dans ces shells. Cependant, notez que bien que supportée par la plupart des shells, cette syntaxe nest pas POSIX et en pratique non supportée par mksh et les dérivés ash.

Donc, pour résumer, avec les shells basés sur pdksh, vous pouvez utiliser des nombres négatifs dans les arguments des fonctions, mais si vous le faites, return "$@" ne fonctionnera pas. Dans dautres shells, return "$@" fonctionnera et vous devriez éviter dutiliser des nombres négatifs (ou des nombres en dehors de 0..255) comme arguments pour return.

  • Dans tous les shells que je connais, appeler return depuis lintérieur dun sous-shell fonctionnant à lintérieur dune fonction provoquera la sortie du sous-shell (avec létat de sortie fourni le cas échéant ou celui de la dernière commande run), mais ne provoquera pas autrement un retour de la fonction (pour moi, il est difficile de savoir si POSIX vous donne cette garantie, certains soutiennent que exit devrait être utilisé à la place des sous-shell de sortie fonctions internes). Par exemple

    f() { (return 3) echo "still inside f. Exit status: $?" } f echo "f exit status: $?" 

    affichera:

    still inside f. Exit status: 3 f exit status: 0 
  • Réponse

    Oui, la valeur de retour implicite dune fonction est létat de sortie du dernier exécuté Commande . Cela est également vrai à tout moment de tout script shell. À tout moment de la séquence dexécution du script, létat de sortie actuel est létat de sortie de la dernière commande exécutée. Même commande exécutée dans le cadre dune affectation de variable: var=$(exit 34). La différence avec les fonctions est qu’une fonction peut changer l’état de sortie à la fin de l’exécution de la fonction.

    L’autre façon de changer le «statut de sortie actuel» est de démarrer un sous-shell et de le quitter avec tout état de sortie nécessaire:

    $ $(exit 34) $ echo "$?" 34 

    Et oui, létat de sortie expansion doivent être cités:

    $ IFS="123" $ $(exit 34) $ echo $? 4 

    Un (exit 34) fonctionne également.
    Certains peuvent argumenter quune construction plus robuste devrait être $(return 34), et quune sortie devrait « quitter » le script en cours dexécution. Mais $(return 34) ne fonctionne pas avec aucune version de bash. Donc, ce nest pas portable.

    Le moyen le plus sûr de définir un statut de sortie est de lutiliser tel quil a été conçu pour fonctionner, définir et return à partir dune fonction :

    exitstatus(){ return "${1:-"$?"}"; } 

    Donc, à la fin dune fonction. cela équivaut exactement à navoir rien ou return ou return "$?". La fin dune fonction na pas besoin de signifier la « dernière ligne de code dune fonction ».

    #!/bin/sh exitstatus(){ a="${1:-"$?"}"; return "$a"; } gmx(){ if [ "$1" = "one" ]; then printf "foo "; exitstatus 78 return "$?" elif [ "$1" = "two" ]; then printf "baz "; exitstatus 89 return else printf "baz "; exitstatus 90 fi } 

    Affiche:

    $ ./script foo 78 baz 89 baz 90 

    La seule utilisation pratique de "$?" est soit dimprimer sa valeur: echo "$?", soit de stocker dans une variable (car il sagit dune valeur éphémère et change à chaque commande exécutée): exitstatus=$? (noubliez pas de citer la variable dans les commandes comme export EXITSTATUS="$?".

    Dans la commande return, la plage de valeurs valide va généralement de 0 à 255, mais sachez que les valeurs de 126 + n sont utilisés par certains shells pour signaler létat de sortie spécial, donc, la recommandation générale est dutiliser 0-125.

    Laisser un commentaire

    Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *