Bash: pass function as parameter

I need to pass a function as a parameter to Bash. For example, the following code:

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

Must output:

 before Hello world after 

I know that eval incorrect in this context, but this is just an example :)

Any idea?

+46
function parameter-passing bash callback
Apr 15
source share
7 answers

If you do not need something interesting, for example, delaying the evaluation of a function name or its arguments, you do not need eval :

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

does what you want. You can even pass a function and its arguments this way:

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

prints

 before x(): Passed 1st and 2nd after 
+65
Apr 15 '11 at 18:45
source share

no need to use eval

 function x() { echo "Hello world" } function around() { echo "before" var=$($1) echo "after $var" } around x 
+13
Apr 15 2018-11-11T00:
source share

I do not think that someone has fully answered the question. He did not ask if he could repeat the lines in order. Rather, the question author wants to know if he can simulate the behavior of a function pointer.

There are several answers that are very similar to what I would do, and I want to expand it with another example.

From the author:

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

To expand this, we will have the x echo "Hello world: $ 1" function to show when the function actually executes. We will pass a string that is the name of the function "x":

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

To describe this, the string "x" is passed to the function around (), which echos "before" calls the function x (via the variable $ 1, the first parameter passed), passing the argument "HERE", finally the echo after.

As another, it is a methodology for using variables as function names. The variables actually contain a string, which is the name of the function, and (the variable $ arg1 arg2 ...) calls the function that passes the arguments. See below:

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

gives: 30 10 20, where we executed a function with the name "x" stored in the variable Z, and passed parameters 10 20 and 30.

Above, where we refer to functions, assigning variable names to functions, so that we can use a variable instead of actually knowing the function name (which is similar to what you could do in a very classic situation with a function pointer in c to generalize the program stream, but pre-selecting function calls that you will create based on command line arguments).

In bash, these are not function pointers, but variables that reference function names that you later use.

+9
18 Oct '15 at 19:39
source share

You cannot pass anything to a function other than strings. Process substitutions can be fake. Bash tends to hold FIFO until the team is expanded to completion.

Here quick stupid

 foldl() { echo $(($(</dev/stdin)$2)) } < <(tr '\n' "$1" <$3) # Sum 20 random ints from 0-999 foldl + 0 <(while ((n=RANDOM%999,x++<20)); do echo $n; done) 

Functions can be exported, but it is not as interesting as at the beginning. I find this to be mostly useful for creating debugging functions available for scripts or other programs that run scripts.

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

id still gets only the string, which is the name of the function (automatically imported from serialization in the environment) and its arguments.

Pumbaa80's comment on another answer is also good ( eval $(declare -F "$1") ), but it is mostly useful for arrays, not functions, as they are always global. If you were to do this inside a function, all it would do was redefine it so that there is no effect. It cannot be used to create closures or partial functions or "function instances" depending on what is happening in the current area. In the best case, this can be used to store the definition of a function in a string, which is redefined elsewhere, but these functions can also only be hard-coded, unless of course eval is used

Basically, Bash cannot be used like that.

+5
Apr 21 '12 at 12:50
source share

You should have something like:

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

Then you can call around x

+1
Apr 15 '11 at 4:18
source share

It is better to use local variables in your functions. Then the problem arises, how do you get the result for the caller. One mechanism is to replace the command:

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

Here, the result is displayed on stdout, and the caller uses command substitution to capture the value in the variable. Then the variable can be used as needed.

+1
Apr 15 '11 at 4:25
source share

eval is probably the only way to execute it. The only real flaw is its security aspect, since you need to make sure that nothing harmful is transmitted, and only the functions you want to be called will be called, and make sure that it does not have any unpleasant characters, such as ';' in it as well).

So, if you are the one who calls the code, then eval is probably the only way to do this. Note that there are other forms of eval that are likely to work with subcommands ($ () and ``) as well, but they are not more secure and cost more.

0
Apr 15 '11 at 4:16
source share



All Articles