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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 00:38:23  来源:igfitidea点击:

bash: How do I create function from variable?

bashfunction

提问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?

请参阅:如何对 <<EOF >> 包含代码的文件进行分类?

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中的行不展开。如果单词是无引号中,这里的文档的所有行进行参数扩展,命令替换和算术扩展,字符序列\换行符被忽略,\必须使用来引用字符\$`