bash:如何从变量创建函数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7145337/
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: How do I create function from variable?
提问by con-f-use
How do I create a function named from the contents a variable? I want to write a template script that defines a function named after the script's own file name. Something like this (which of course doesn't work):
如何创建一个以变量内容命名的函数?我想编写一个模板脚本,定义一个以脚本自己的文件名命名的函数。像这样的东西(当然不起作用):
#!/bin/bash
bname="$(basename eval "someprefix_${bname}() { echo test; }"
)" # filename of the script itself
someprefix_${bname}() { # function's name created from $bname variable
echo test
}
So if the script's filename is foo.sh, then it should define a function named someprefix_foothat will echo "test".
因此,如果脚本的文件名是foo.sh,那么它应该定义一个名为someprefix_foo“test”的函数。
回答by Eugene Yarmash
You can use eval:
您可以使用eval:
source /dev/stdin <<EOF
function someprefix_${bname}()
{
echo "test";
};
EOF
Bash even allows "."s in function names :)
Bash 甚至允许"."在函数名称中使用s :)
回答by blake private_last_name
Indeed, it is instructive that the aforementioned construction derails the possibility of having embedded quotation marks there within and is thus potentially bugulant. However, the following construction does proffer similar functionality whilst not having the constraints of the former answer.
事实上,上述结构破坏了在其中嵌入引号的可能性,因此可能会引起争议,这一点很有启发性。但是,以下构造确实提供了类似的功能,同时没有前一个答案的限制。
For your review:
供您审核:
source /dev/stdin << EOF
badfunc ()
{
echo $(date)
}
EOF
$ date;badfunc;sleep 10;date;badfunc
Tue Dec 1 12:34:26 EST 2015 ## badfunc output not current
Tue Dec 1 12:23:51 EST 2015
Tue Dec 1 12:34:36 EST 2015 ## and not changing
Tue Dec 1 12:23:51 EST 2015
回答by mpersico
The 'eval and 'source' solutions work IFF you do not have anything in the function that could be evaluated at create time that you actuallywant delayed until execution time.
'eval 和'source' 解决方案适用于IFF,您在创建时没有任何可以在创建时进行评估的功能,而您实际上希望延迟到执行时间。
tmpsh=$(mktemp)
echo "goodfunc ()" > $tmpsh
echo '{' >> $tmpsh
echo 'echo $(date)' >> $tmpsh
echo '}' >> $tmpsh
. $tmpsh
rm -f $tmpsh
Yes, it's a contrived example (just call date and don't echo a subshell call of it), but using the original answers, I tried something a more elaborate that required a run time evaluation and got similar results - evaluation at "compile" time, not run time.
是的,这是一个人为的例子(只是调用 date 并且不回显它的子shell调用),但是使用原始答案,我尝试了一些更复杂的东西,需要运行时评估并得到类似的结果 - 在“编译”时评估时间,而不是运行时间。
The way that I solved the problem was to build a temp file with the function and then source that. By the judicious use of single and double quotes surrounding the test I print into the file, I can completely control what gets evaluated and when.
我解决问题的方法是使用该函数构建一个临时文件,然后获取该文件。通过在我打印到文件中的测试周围明智地使用单引号和双引号,我可以完全控制评估什么以及何时评估。
$ date;goodfunc;sleep 10;date;goodfunc
Tue Dec 1 12:36:42 EST 2015 ## current
Tue Dec 1 12:36:42 EST 2015
Tue Dec 1 12:36:52 EST 2015 ## and advancing
Tue Dec 1 12:36:52 EST 2015
and then
进而
eval "$(cat <<EOF
$function_name() {
commands go here
but "$you $have $to $escape $variables"
}
EOF
)"
Hopefully, this will be of more use to people. Enjoy.
希望这对人们更有用。享受。
回答by dimo414
I use the following syntax, which avoids /dev/stdinbut still lets you use heredocs:
我使用以下语法,它避免了/dev/stdin但仍然允许您使用heredocs:
eval "$(cat <<EOF
$function_name() {
commands go here
and "$you $do $not $have $to $escape variables"
}
EOF
)"
(notice $variableswill be expanded in the function body, the other vars will not be).
(注意$variables将在函数体中展开,其他变量不会)。
回答by Léa Gris
You can disable expansion of a Here Documentlike that:
您可以像这样禁用Here Document 的扩展:
##代码##See: How to cat <<EOF >> a file containing code?
Bash Manual: 3.6.6 Here Documents / Here Document
No parameter and variable expansion, command substitution, arithmetic expansion, or filename expansion is performed on word. If any part of word is quoted, the delimiter is the result of quote removal on word, and the lines in the here-document are not expanded. If word is unquoted, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion, the character sequence \newline is ignored, and
\must be used to quote the characters\,$, and`.
Bash 手册:3.6.6 Here Documents / Here Document
不会对 word 执行参数和变量扩展、命令替换、算术扩展或文件名扩展。如果word的任何部分被引用,则分隔符是对word去除引用的结果,并且here-document中的行不展开。如果单词是无引号中,这里的文档的所有行进行参数扩展,命令替换和算术扩展,字符序列\换行符被忽略,
\必须使用来引用字符\,$和`。

