6

I'm trying to define a bash function dynamically using following code:

delegate_function() { echo "output from delegate"; }
eval "parent_function() { echo $(delegate_function); }"

The intent is to have parent function dynamically dispatch to the delegate when executed. However due to the way eval works my function is being defined as follows:

kshitiz:/tmp$ type parent_function
parent_function is a function
parent_function () 
{ 
    echo output from delegate
}

How can I instead have the definition as:

 parent_function () 
 { 
     echo $(delegate_function);
 }

Is there a way to escape some part of the string from being evaluated by eval?

3 Answers 3

12

In bash, like in most languages, eval is something to avoid. See, for example, Greg's FAQ: Eval command and security issues

You can define parent_function like this:

parent_function=delegate_function

Anytime that you want to use parent_function to dispatch delegate_function, just run:

$ $parent_function
output from delegate

Example of dynamic function update

Let's define delegate_function and parent_function and run $parent_function:

$ delegate_function() { echo "delegate version 1"; }
$ parent_function=delegate_function
$ $parent_function
delegate version 1

Now let's change delegate_function and run $parent_function again:

$ delegate_function() { echo "delegate version 2"; }
$ $parent_function
delegate version 2

$parent_function instantly updates to run the new version of delegate_function.

Example of dynamic choice of name

Let's create our delegate function:

$ delegate_function() { echo "delegate function executed"; }

Let's assign some name:

$ parent_function=some_name

Now, let's demonstrate dynamic assignment of that name:

$ typeset $parent_function=delegate_function
$ $some_name
delegate function executed
4
  • 1
    That link should be trumpeted far and wide; thanks for providing it.
    – Wildcard
    Commented May 12, 2016 at 4:19
  • 1
    Though I appreciate the warning about pitfalls of eval, this does not satisfy my requirements as it hard codes the parent function name, while I need it to be dynamic. adonis' answer provides the right solution. Commented May 12, 2016 at 9:43
  • @John1024 Sorry what I meant is that parent_function is hardcoded in code. Its name should come from contents of a variable. Sometimes grandpa_function other times xt738_function. Commented May 12, 2016 at 21:31
  • Background: I want to automatically define shell based wrappers for my golang functions. My shell script will scan a directory for golang files, read the function names and then define bash functions with same names that internally invoke the golang functions. There's no security risk here as I'm not evaluating user input, just defining a convenient means to access my own golang functions. Commented May 12, 2016 at 21:33
7

Escaping $ should be enough to make this work:

eval "parent_function() { echo \$(delegate_function); }"
0

If you want parent_function to produce the output from delegate_function, along with some other stuff, e.g.,

parent_function()
{
    other command(s)
    echo $(delegate_function)
    other command(s)
}

then, if the output from delegate_function is just a single line, you can simplify the above to

parent_function()
{
    other command(s)
    delegate_function
    other command(s)
}

P.S. You don't need to use ; at the end of a line; use it (as a separator) only when you're putting multiple things on the same line.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .