如何在 Bash 中的另一个函数中定义一个函数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8426077/
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-09 21:18:46  来源:igfitidea点击:

How to define a function inside another function in Bash?

bash

提问by tiranodev

I have the following code

我有以下代码

func1(){
    #some function thing
    function2(){
        #second function thing
    }
}

and I want to call function2but I get an error function2 : not found

我想打电话function2但我收到一个错误function2 : not found

Is there a solution?

有解决办法吗?

回答by Gordon Davisson

Function definitions in bash don't work the way function definitions work in many other languages. In bash, a function definition is an executablecommand which defines the effect of a function (replacing any previous definition), in much the same way that a variable assignment command defines the value of a variable (replacing any previous definition). Perhaps this example will clarify what I mean:

bash 中的函数定义不像许多其他语言中的函数定义那样工作。在 bash 中,函数定义是一个可执行命令,它定义函数的效果(替换任何以前的定义),与变量赋值命令定义变量的值(替换任何以前的定义)非常相似。也许这个例子会澄清我的意思:

$ outerfunc1() {
> innerfunc() { echo "Running inner function #1"; }
> echo "Running outer function #1"
> }
$ outerfunc2() {
> innerfunc() { echo "Running inner function #2"; }
> echo "Running outer function #2"
> }
$
$ # At this point, both outerfunc1 and outerfunc2 contain definitions of
$ # innerfunc, but since neither has been executed yet, the definitions
$ # haven't "happened".
$ innerfunc
-bash: innerfunc: command not found
$
$ outerfunc1
Running outer function #1
$ # Now that outerfunc1 has executed, it has defined innerfunc:
$ innerfunc
Running inner function #1
$
$ outerfunc2
Running outer function #2
$ # Running outerfunc2 has redefined innerfunc:
$ innerfunc
Running inner function #2

Now, if you didn't already know this, I'm pretty sure this wasn't your reason for nesting function definitions. Which brings up the question: why areyou nesting function definitions at all? Whatever effect you expected nested definitions to have, that's not what they do in bash; so 1) unnest them and 2) find some other way to accomplish whatever you were trying to get the nesting to do for you.

现在,如果您还不知道这一点,我很确定这不是您嵌套函数定义的原因。这带来了一个问题:为什么你在所有嵌套函数的定义?无论您期望嵌套定义产生什么效果,这都不是它们在 bash 中所做的;所以 1) 取消嵌套它们 2) 找到其他一些方法来完成您试图让嵌套为您做的任何事情。

回答by Teudimundo

In the question case I suppose that you were trying to call function2 before it is defined, "some function thing" should have been after the function2 definition.

在问题案例中,我假设您在定义 function2 之前尝试调用它,“某些功能的东西”应该在 function2 定义之后。

For the sake of discussion, I have a case where using such definitions can be of some use.

为了讨论起见,我有一个案例,使用这样的定义可能会有用。

Suppose you want to provide a function that might be complex, its readability could be helped by splitting the code in smaller functions but you don't want that such functions are made accessible.

假设您想提供一个可能很复杂的函数,可以通过将代码拆分为更小的函数来提高其可读性,但您不希望这些函数可访问。

Running the following script (inner_vs_outer.sh)

运行以下脚本(inner_vs_outer.sh)

#!/bin/bash
function outer1 {
    function inner1 {
       echo '*** Into inner function of outer1'
    }
    inner1;
    unset -f inner1
}

function outer2 {
    function inner2 {
       echo '*** Into inner function of outer2'
    }
    inner2;
    unset -f inner2
}
export PS1=':inner_vs_outer$ '
export -f outer1 outer2

exec bash -i

when executed a new shell is created. Here outer1 and outer2 are valid commands, but inner is not, since it has been unset exiting from where you have outer1 and outer2 defined but inner is not and will not be because you unset it at the end of the function.

执行时会创建一个新的shell。这里的outer1 和outer2 是有效的命令,但inner 不是,因为它已经从定义outer1 和outer2 的地方退出,但inner 不是也不会是,因为你在函数的末尾取消了它。

$ ./inner_vs_outer.sh
:inner_vs_outer$ outer1
*** Into inner function of outer1
:inner_vs_outer$ outer2
*** Into inner function of outer2
:inner_vs_outer$ inner1
bash: inner1: command not found
:inner_vs_outer$ inner2
bash: inner2: command not found

Note that if you define the inner functions at the outer level and you don't export them they will not be accessible from the new shell, but running the outer function will result in errors because they will try executing functions no longer accessible; instead, the nested functions are defined every time the outer function is called.

请注意,如果您在外部级别定义内部函数并且不导出它们,则它们将无法从新 shell 访问,但运行外部函数将导致错误,因为它们将尝试执行不再可访问的函数;相反,每次调用外部函数时都会定义嵌套函数。

回答by Charlie Martin

Don't nest function definitions. replace with:

不要嵌套函数定义。用。。。来代替:

$ cat try.bash 
function one {
  echo "One"
}

function two {
  echo "Two"
}

function three {
   one
   two
}

three
$ bash try.bash 
One
Two
$ 

回答by Brian

If you're nesting a function, say function2 inside function1, it doesn't become available until function1 is called. Some people might consider this a feature, as you can do something like "unset function2" at the end of function1 and its scope is completely local to that function (can't be called from elsewhere). If you want to call the function elsewhere, there's probably no need to nest it anyway.

如果您正在嵌套一个函数,例如在 function1 中的 function2,则在调用 function1 之前它不会变得可用。有些人可能认为这是一个功能,因为您可以在 function1 的末尾执行诸如“unset function2”之类的操作,并且它的作用域完全是该函数的本地(不能从其他地方调用)。如果您想在别处调用该函数,则可能无论如何都不需要嵌套它。

回答by ivan_pozdeev

Your code should work as written provided you only call the nested function after it's defined.

如果您只在定义后调用嵌套函数,您的代码应该按编写的方式工作

As said in another answer, a func(){<...>}statement is an executable statement that defines a name (in the global scope) associated with the function.Just like if you defined a variable.

作为另一个答案说一个func(){<...>}说法是与功能相关联的定义的名称(在全球范围内)的可执行语句。就像你定义了一个变量一样。

So, you can use func2anywhere in the code after the func2(){<...>}statement has run:

因此,您可以func2func2(){<...>}语句运行后在代码中的任何位置使用:

#func2 not defined
func1(){
    #not defined
    func2(){<...>}
    #defined
}
#not defined
func1
#defined
func3(){
    #only defined if func3 is called after `func2(){<...>}' has run
}