Bash:将函数作为参数传递
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5672289/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Bash: pass a function as parameter
提问by cd1
I need to pass a function as a parameter in Bash. For example, the following code:
我需要在 Bash 中传递一个函数作为参数。例如,以下代码:
function x() {
echo "Hello world"
}
function around() {
echo "before"
eval
echo "after"
}
around x
Should output:
应该输出:
before
Hello world
after
I know eval
is not correct in that context but that's just an example :)
我知道eval
在这种情况下是不正确的,但这只是一个例子:)
Any idea?
任何的想法?
回答by Idelic
If you don't need anything fancy like delaying the evaluation of the function name or its arguments, you don't need eval
:
如果您不需要像延迟函数名称或其参数的计算这样的花哨的东西,则不需要eval
:
function x() { echo "Hello world"; }
function around() { echo before; ; echo after; }
around x
does what you want. You can even pass the function and its arguments this way:
做你想做的。您甚至可以通过这种方式传递函数及其参数:
function x() { echo "x(): Passed and "; }
function around() { echo before; "$@"; echo after; }
around x 1st 2nd
prints
印刷
before
x(): Passed 1st and 2nd
after
回答by uDude
I don't think anyone quite answered the question. He didn't ask if he could echo strings in order. Rather the author of the question wants to know if he can simulate function pointer behavior.
我认为没有人完全回答这个问题。他没有问他是否可以按顺序回显字符串。相反,问题的作者想知道他是否可以模拟函数指针行为。
There are a couple of answers that are much like what I'd do, and I want to expand it with another example.
有几个答案与我所做的很相似,我想用另一个例子来扩展它。
From the author:
来自作者:
function x() {
echo "Hello world"
}
function around() {
echo "before"
() <------ Only change
echo "after"
}
around x
To expand this, we will have function x echo "Hello world:$1" to show when the function execution really occurs. We will pass a string that is the name of the function "x":
为了扩展它,我们将使用函数 x echo "Hello world:$1" 来显示函数真正执行的时间。我们将传递一个字符串,它是函数“x”的名称:
function x() {
echo "Hello world:"
}
function around() {
echo "before"
( 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 to around) passing the argument "HERE", finally echos after.
为了描述这一点,字符串“x”被传递给函数around(),它回显“before”,调用函数x(通过变量$1,传递给around的第一个参数)传递参数“HERE”,最后回显after .
As another aside, this is the methodology to use variables as function names. The variables actually hold the string that is the name of the function and ($variable arg1 arg2 ...) calls the function passing the arguments. See below:
另一方面,这是使用变量作为函数名的方法。变量实际上包含作为函数名称的字符串,并且 ($variable arg1 arg2 ...) 调用传递参数的函数。见下文:
function x(){
echo <== just rearrange the order of passed params
}
Z="x" # or just Z=x
($Z 10 20 30)
gives: 30 10 20, where we executed the function named "x" stored in variable Z and passed parameters 10 20 and 30.
给出:30 10 20,其中我们执行了存储在变量 Z 中的名为“x”的函数,并传递了参数 10 20 和 30。
Above where we reference functions by assigning variable names to the functions so we can use the variable in place of actually knowing the function name (which is similar to what you might do in a very classic function pointer situation in c for generalizing program flow but pre-selecting the function calls you will be making based on command line arguments).
在上面,我们通过为函数分配变量名来引用函数,这样我们就可以使用变量代替实际知道函数名(这类似于您在 c 中非常经典的函数指针情况下可能会做的用于泛化程序流程的操作,但是预先- 选择您将根据命令行参数进行的函数调用)。
In bash these are not function pointers, but variables that refer to names of functions that you later use.
在 bash 中,这些不是函数指针,而是引用您以后使用的函数名称的变量。
回答by kurumi
there's no need to use eval
没有必要使用 eval
function x() {
echo "Hello world"
}
function around() {
echo "before"
var=$()
echo "after $var"
}
around x
回答by ormaaj
You can't pass anything to a function other than strings. Process substitutions can sort of fake it. Bash tends to hold open the FIFO until a command its expanded to completes.
除了字符串,您不能将任何内容传递给函数。过程替换可以有点伪造它。Bash 倾向于保持打开 FIFO,直到其扩展完成的命令。
Here's a quick silly one
这是一个快速愚蠢的
foldl() {
echo $(($(</dev/stdin)))
} < <(tr '\n' "" <)
# Sum 20 random ints from 0-999
foldl + 0 <(while ((n=RANDOM%999,x++<20)); do echo $n; done)
Functions can be exported, but this isn't as interesting as it first appears. I find it's mainly useful for making debugging functions accessible to scripts or other programs that run scripts.
可以导出函数,但这并不像最初出现的那样有趣。我发现它主要用于使脚本或其他运行脚本的程序可以访问调试功能。
(
id() {
"$@"
}
export -f id
exec bash -c 'echowrap() { echo ""; }; id echowrap hi'
)
id
still only gets a string that happens to be the name of a function (automatically imported from a serialization in the environment) and its args.
id
仍然只获取一个恰好是函数名称的字符串(从环境中的序列化自动导入)及其参数。
Pumbaa80's comment to another answer is also good (eval $(declare -F "$1")
), but its mainly useful for arrays, not functions, since they're always global. If you were to run this within a function all it would do is redefine it, so there's no effect. It can't be used to create closures or partial functions or "function instances" dependent on whatever happens to be bound in the current scope. At best this can be used to store a function definition in a string which gets redefined elsewhere - but those functions also can only be hardcoded unless of course eval
is used
Pumbaa80 对另一个答案的评论也很好 ( eval $(declare -F "$1")
),但它主要用于数组,而不是函数,因为它们始终是全局的。如果你在一个函数中运行它,它所做的就是重新定义它,所以没有效果。它不能用于创建闭包或部分函数或“函数实例”,这取决于当前作用域中发生的任何绑定。充其量这可用于将函数定义存储在字符串中,该字符串在其他地方重新定义 - 但这些函数也只能硬编码,除非当然eval
使用
Basically Bash can't be used like this.
基本上 Bash 不能像这样使用。
回答by Anand Thangappan
A better approach is to use local variables in your functions. The problem then becomes how do you get the result to the caller. One mechanism is to use command substitution:
更好的方法是在函数中使用局部变量。那么问题就变成了如何将结果传递给调用者。一种机制是使用命令替换:
function myfunc()
{
local myresult='some value'
echo "$myresult"
}
result=$(myfunc) # or result=`myfunc`
echo $result
Here the result is output to the stdout and the caller uses command substitution to capture the value in a variable. The variable can then be used as needed.
这里的结果输出到标准输出,调用者使用命令替换来捕获变量中的值。然后可以根据需要使用该变量。
回答by Tim O
You should have something along the lines of:
你应该有一些类似的东西:
function around()
{
echo 'before';
echo ``;
echo 'after';
}
You can then call around x
然后你可以打电话 around x
回答by Wes Hardaker
eval is likely the only way to accomplish it. The only real downside is the security aspect of it, as you need to make sure that nothing malicious gets passed in and only functions you want to get called will be called (along with checking that it doesn't have nasty characters like ';' in it as well).
eval 可能是实现它的唯一方法。唯一真正的缺点是它的安全性方面,因为您需要确保没有任何恶意内容被传入,并且只会调用您想要调用的函数(同时检查它是否没有像“;”这样令人讨厌的字符)也在其中)。
So if you're the one calling the code, then eval is likely the only way to do it. Note that there are other forms of eval that would likely work too involving subcommands ($() and ``), but they're not safer and are more expensive.
因此,如果您是调用代码的人,那么 eval 可能是唯一的方法。请注意,还有其他形式的 eval 可能也适用于涉及子命令($() 和 ``),但它们并不安全且成本更高。