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

时间:2011-12-08 04:14:47

标签: bash

我有以下代码

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

我想致电function2,但收到错误function2 : not found

有解决方案吗?

6 个答案:

答案 0 :(得分:56)

限制内部功能的范围

使用用括号()定义的函数代替大括号{}

f() (
  g() {
    echo G
  }
  g
)

# Ouputs `G`
f
# Command not found.
g

括号函数在子shell中运行,子shell具有与() vs {}相同的语义,另请参阅:Defining bash function body using parenthesis instead of braces

如果您想要:

,则无法使用
  • 设置变量
  • exit
  • cd

因为那些在创建的子shell中丢失了。

另请参阅:bash functions: enclosing the body in braces vs. parentheses

答案 1 :(得分:43)

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

现在,如果您还不知道这一点,我很确定这不是您嵌套函数定义的原因。这提出了一个问题:为什么 你完全嵌套函数定义?无论你期望嵌套定义有什么影响,这都不是他们在bash中所做的;所以1)不要他们和2)找到其他方法来完成你想要为你做的任何事情。

答案 2 :(得分:12)

不嵌套函数定义。替换为:

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

function two {
  echo "Two"
}

function three {
   one
   two
}

three
$ bash try.bash 
One
Two
$ 

答案 3 :(得分:12)

在问题情况下,我认为你在定义之前试图调用function2,"某些功能的东西"应该是在function2定义之后。

为了便于讨论,我有一个案例,使用这些定义可以有所帮助。

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

运行以下脚本(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

执行时会创建一个新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

请注意,如果在外层定义内部函数并且不导出它们,则无法从新she​​ll中访问它们,但运行外部函数将导致错误,因为它们将尝试执行函数no更容易接近;相反,每次调用外部函数时都会定义嵌套函数。

答案 4 :(得分:2)

如果您正在嵌套一个函数,比如function1中的function2,那么在调用function1之前它不可用。有些人可能会认为这是一个功能,因为你可以做一些像" unset function2"在function1的末尾,它的范围对于该函数是完全本地的(不能从其他地方调用)。如果你想在其他地方调用该函数,那么无论如何都可能不需要嵌套它。

答案 5 :(得分:0)

您的代码应该以书面的方式工作,前提是您只能在定义之后调用嵌套函数。

As said in another answer func2语句是一个可执行语句,用于定义与该函数关联的名称(在全局范围内)。就像定义了一个变量一样。

因此,您可以在func2(){<...>}语句运行后在代码中的任何位置使用#func2 not defined func1(){ #not defined func2(){<...>} #defined } #not defined func1 #defined func3(){ #only defined if func3 is called after `func2(){<...>}' has run }

{{1}}