Bash:传递一个函数作为参数

我需要在Bash中传递一个参数作为参数。 例如,下面的代码:

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

应该输出:

 before Hello world after 

我知道在这方面eval是不正确的,但这只是一个例子:)

任何想法?

如果您不需要像延迟函数名称或其参数的评估那样的任何幻想,则不需要eval

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

做你想要的。 你甚至可以这样传递函数和参数:

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

版画

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

没有必要使用eval

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

我不认为有人回答这个问题。 他没有问他是否可以按顺序回音。 而问题的作者想知道他是否可以模拟函数指针的行为。

有几个答案很像我想做的,我想用另一个例子来扩展它。

来自作者:

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

为了扩大这个范围,我们将有函数x echo“Hello world:$ 1”来显示函数执行真正发生的时间。 我们将传递一个string,它是函数“x”的名字:

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

为了描述这个,string“x”被传递给函数around(),它callback“之前”,调用函数x(通过variables$ 1,第一个parameter passing给周围),通过参数“HERE”,最后回声。

另一方面,这是使用variables作为函数名称的方法。 variables实际上保存了作为函数名称的string,($ variable arg1 arg2 …)调用传递参数的函数。 见下文:

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

给出:30 10 20,我们执行存储在variablesZ中的名为“x”的函数,并传递参数10 20和30。

上面我们通过给函数指定variables名来引用函数,所以我们可以使用variables来代替实际上知道函数名的地方(这与您在c中用于概括程序stream的非常经典的函数指针情况中可能做的类似) – 根据命令行参数select函数调用)。

在bash中,这些不是函数指针,而是指向稍后使用的函数名称的variables。

你不能传递任何东西给string以外的函数。 stream程replace可以把它伪造。 Bash往往会保持开放的FIFO直到一个命令扩展到完成。

这是一个快速愚蠢的

 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) 

函数可以被导出,但是这并不像它第一次出现那样有趣。 我发现它主要用于使脚本或运行脚本的其他程序可以访问debuggingfunction。

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

id仍然只得到一个string恰好是一个函数的名称(从环境中的序列化自动导入)及其参数。

Pumbaa80对另一个答案的评论也很好( eval $(declare -F "$1") ),但是它主要用于数组,而不是函数,因为它们总是全局的。 如果你要在一个函数中运行它,所有它将会重新定义它,所以没有任何效果。 它不能用于创build闭包或部分函数或“函数实例”,取决于在当前范围内发生的任何事情。 最好这可以用来存储一个函数定义在一个string中得到重新定义 – 但这些函数也只能被硬编码,除非当然使用eval

基本上Bash不能这样使用。

更好的方法是在函数中使用局部variables。 那么问题就变成了如何让调用者得到结果。 一种机制是使用命令replace:

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

这里的结果输出到标准输出,调用者使用命令replace捕获variables中的值。 然后可以根据需要使用该variables。

你应该有以下几点:

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

然后你可以打电话给around x

eval可能是实现它的唯一方法。 唯一真正的缺点是它的安全性方面,因为你需要确保没有任何恶意被传入,只有你想调用的函数会被调用(同时检查它没有恶意字符,如';'也在其中)。

所以如果你是调用代码的人,那么评估可能是唯一的方法。 请注意,还有其他forms的eval可能会涉及子命令($()和“),但它们并不安全并且更昂贵。