Bash: passer une fonction en paramètre

Je dois passer une fonction en tant que paramètre dans Bash. Par exemple, le code suivant:

function x() { echo "Hello world" } function around() { echo "before" eval $1 echo "after" } around x 

Devrait sortir:

 before Hello world after 

Je sais eval n’est pas correct dans ce contexte mais c’est juste un exemple 🙂

Une idée?

    Si vous n’avez besoin de rien comme de retarder l’évaluation du nom de la fonction ou de ses arguments, vous n’avez pas besoin d’ eval :

     function x() { echo "Hello world"; } function around() { echo before; $1; echo after; } around x 

    fait ce que tu veux Vous pouvez même passer la fonction et ses arguments de cette façon:

     function x() { echo "x(): Passed $1 and $2"; } function around() { echo before; "$@"; echo after; } around x 1st 2nd 

    estampes

     before x(): Passed 1st and 2nd after 

    il n’y a pas besoin d’utiliser eval

     function x() { echo "Hello world" } function around() { echo "before" var=$($1) echo "after $var" } around x 

    Je pense que personne n’a répondu à la question. Il n’a pas demandé s’il pouvait faire écho aux cordes. L’auteur de la question veut plutôt savoir s’il peut simuler un comportement de pointeur de fonction.

    Il y a quelques réponses qui ressemblent beaucoup à ce que je ferais, et je veux les développer avec un autre exemple.

    De l’auteur:

     function x() { echo "Hello world" } function around() { echo "before" ($1) <------ Only change echo "after" } around x 

    Pour développer cela, nous aurons la fonction x echo "Hello world: $ 1" pour montrer quand l'exécution de la fonction se produit réellement. Nous allons passer une chaîne qui est le nom de la fonction "x":

     function x() { echo "Hello world:$1" } function around() { echo "before" ($1 HERE) <------ Only change echo "after" } around x 

    Pour décrire cela, la chaîne "x" est passée à la fonction around () qui fait écho "before", appelle la fonction x (via la variable $ 1, le premier paramètre passé à around) en passant l'argument "HERE", enfin echos après .

    Autre sharepoint vue, il s’agit de la méthodologie pour utiliser les variables comme noms de fonctions. Les variables contiennent réellement la chaîne qui est le nom de la fonction et ($ variable arg1 arg2 ...) appelle la fonction en passant les arguments. Voir ci-dessous:

     function x(){ echo $3 $1 $2 <== just rearrange the order of passed params } Z="x" # or just Z=x ($Z 10 20 30) 

    donne: 30 10 20, où nous avons exécuté la fonction nommée "x" stockée dans la variable Z et passé les parameters 10 20 et 30.

    Ci-dessus, où nous référençons des fonctions en assignant des noms de variables aux fonctions afin que nous puissions utiliser la variable au lieu de connaître le nom de la fonction (ce qui est similaire à une situation très classique de pointeur pour généraliser des stream de programmes -Sélectionner les appels de fonction que vous allez effectuer en fonction des arguments de la ligne de commande).

    Dans bash ce ne sont pas des pointeurs de fonction, mais des variables qui font référence à des noms de fonctions que vous utiliserez ultérieurement.

    Vous ne pouvez rien transmettre à une fonction autre que des chaînes. Les substitutions de processus peuvent en quelque sorte le tromper. Bash a tendance à maintenir ouvert le FIFO jusqu’à ce qu’une commande soit complétée.

    Voici un idiot rapide

     foldl() { echo $(($( 

    Les fonctions peuvent être exscopes, mais ce n’est pas aussi intéressant qu’au premier abord. Je trouve que c'est principalement utile pour rendre les fonctions de débogage accessibles aux scripts ou à d'autres programmes qui exécutent des scripts.

     ( id() { "$@" } export -f id exec bash -c 'echowrap() { echo "$1"; }; id echowrap hi' ) 

    id n'obtient toujours qu'une chaîne qui se trouve être le nom d'une fonction (imscope automatiquement depuis une sérialisation dans l'environnement) et ses arguments.

    Le commentaire de Pumbaa80 à une autre réponse est également bon ( eval $(declare -F "$1") ), mais il est principalement utile pour les tableaux, pas pour les fonctions, car ils sont toujours globaux. Si vous deviez exécuter cela dans une fonction, tout ce qu'il ferait, c'est le redéfinir, donc il n'y a pas d'effet. Il ne peut pas être utilisé pour créer des fermetures ou des fonctions partielles ou des "instances de fonction" dépendant de ce qui se trouve lié à la scope actuelle. Au mieux, cela peut être utilisé pour stocker une définition de fonction dans une chaîne qui est redéfinie ailleurs - mais ces fonctions ne peuvent également être codées que si bien sûr eval est utilisé

    Fondamentalement, Bash ne peut pas être utilisé comme ça.

    Une meilleure approche consiste à utiliser des variables locales dans vos fonctions. Le problème devient alors comment obtenez-vous le résultat à l’appelant. Un mécanisme consiste à utiliser la substitution de commandes:

     function myfunc() { local myresult='some value' echo "$myresult" } result=$(myfunc) # or result=`myfunc` echo $result 

    Ici, le résultat est envoyé à la sortie standard et l’appelant utilise la substitution de commandes pour capturer la valeur dans une variable. La variable peut alors être utilisée selon les besoins.

    Vous devriez avoir quelque chose comme:

     function around() { echo 'before'; echo `$1`; echo 'after'; } 

    Vous pouvez alors appeler around x

    eval est probablement le seul moyen d’y parvenir. Le seul inconvénient est l’aspect sécurité, car vous devez vous assurer que rien de malveillant n’est transmis et que seules les fonctions que vous voulez appeler seront appelées (tout en vérifiant qu’il n’y a pas de personnages méchants comme ‘;’ dans elle aussi).

    Donc, si vous appelez le code, eval est probablement le seul moyen de le faire. Notez qu’il existe d’autres formes d’évaluation qui fonctionneraient probablement avec des sous-commandes ($ () et “), mais elles ne sont pas plus sûres et coûtent plus cher.