下面声明的调用函数


15

是否可以调用下面在bash中声明的函数?

if [ "$input" = "yes" ]; then
    YES_FUNCTION
elif [ "$input" = "no" ]; then
    NO_FUNCTION
else
    exit 0;
fi

YES_FUNCTION()
{
  .....
  .....
}

NO_FUNCTION()
{
  .....
  .....
}

Answers:


37

就像其他人说的那样,您不能那样做。

但是,如果要将代码安排到一个文件中,以便主程序位于文件的顶部,并且在下面定义了其他功能,则可以通过使用单独的main功能来实现。

例如

#!/bin/sh

main() {
    if [ "$1" = yes ]; then
        do_task_this
    else
        do_task_that
    fi
}

do_task_this() {
    ...
} 
do_task_that() {
    ...
} 

main "$@"; exit

当我们main在文件末尾调用时,所有函数都已定义。要使脚本的命令行参数在函数中可见,需要显式传递"$@"main

exit与main调用位于同一行的显式命令不是强制性的,但是如果修改了脚本文件,则可用于防止正在运行的脚本陷入混乱。没有它,shell将在main返回后尝试继续从脚本文件读取命令。(请参阅如何在执行之前读取整个shell脚本?


@ikkachu认为它应该工作..让我检查一下。
msp9011

8
使用Bash脚本时,我经常使用它[[ ${BASH_SOURCE[0]} = "$0" ]] && Main "$@"来调用main函数,这样我就可以在另一个脚本中获取Main其源代码而无需执行。然后,我可以重用这些功能或编写测试来检查它们。
BlackJack

11
具有main "$@"; exit(与exit相同的行main)还可以用作防止文件在被解释时被修改的保护措施。
斯特凡Chazelas

2
@JoL,不再读取读取的内容,外壳程序将需要在开始运行之前读取并解析循环的整个文本,但是在循环返回之后,它将继续从文件的其余部分进行读取当前位置(如果文件已被修改,则可能会搞砸)。如果一切都在函数中,那么如果我们将shell exit放在同一行,因为main我们确保shell在main返回后不会再从文件中读取任何内容,那么外壳需要在开始执行任何操作之前先读取所有内容。
斯特凡Chazelas

1
@MontyHarder,这不要紧,如果你使用main; exitmain; exit $?或者main <EOF>,在所有情况下的退出代码main作为脚本的退出代码。该exit会只是为了防止事情越来越乱了,如果有人编辑,而它的运行脚本。
ilkkachu

13

不,函数在调用它们时必须存在于shell环境中。

Google的“外壳样式指南”对此进行了修复:

调用的函数main所需的脚本足够长以包含至少一种其他功能。

在脚本的最后,所有函数之后,作为唯一不在函数中的语句,您将拥有

main "$@"

这将main使用脚本给出的任何参数调用该函数。该main函数可以位于脚本的顶部(样式指南说将其放在底部,但随后又说了很多事情)。

当shell进入main调用时,脚本中的所有函数都已解析,因此可以从main函数内部调用。


9

不,必须在使用函数之前声明它们。Shell脚本逐行读取并逐行执行;因此,函数必须在其声明执行后才存在。


你是对的。问题是我在脚本中有30多个函数。当我们阅读代码时,这非常棘手。在C它的舒适。
msp9011

3
您可以将函数声明放在另一个文件中并作为源文件(. yourfile)。
Stephen Kitt

是的,我已经尝试过了,但是要求是有一个脚本。
msp9011

@SivaPrasath到底是什么问题?只需定义所有函数,甚至可以将主代码放入函数中,然后最后一行显示调用了哪个函数并包含脚本的主要部分。
BlackJack

@SivaPrasath在C语言中,if函数外没有裸露的语句。声明if -include函数时,不必在调用时定义该函数。
chepner

4

外壳没有declaring功能的概念。因此,您不能有前向声明。

因此,您需要让外壳读取函数实现,然后才能调用它。


4
从技术上讲,某些外壳程序(ksh,zsh)具有函数自动加载功能,可以将其视为某种形式的声明(在其中autoload f声明函数,但其​​主体仅在第一次调用时加载)。但是,这不适用于OP bash
斯特凡Chazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.