9

我有一个 Bourne Shell 脚本,其中包含多个函数,并允许通过以下方式调用:

my.sh <func_name> <param1> <param2>

在内部,func_name()将使用param1and调用param2

我想创建一个help只列出所有可用函数的函数,即使没有参数。

问题:如何从脚本内部获取脚本中所有函数名称的列表?

我想避免解析它并寻找函数模式。太容易出错了。

更新:代码。希望我的help()功能像main()- 添加到代码中的功能会自动添加到帮助中。

#!/bin/sh

# must work with "set -e"

foo ()
{
    echo foo: -$1-$2-$3-
    return 0
}

# only runs if there are parameters
# exits
main ()
{
    local cmd="$1"
    shift
    local rc=0
    $cmd "$@" || rc=$?
    exit $rc
}

if [[ "$*" ]]
then
    main "$@"
    die "how did we get here?"
fi
4

4 回答 4

16

您可以通过在自己的脚本上使用 grep 命令来获取脚本中的函数列表。为了使这种方法起作用,您需要以某种方式构造函数,以便 grep 可以找到它们。这是一个示例:

$ cat my.sh
#!/bin/sh

function func1() # Short description
{
    echo func1 parameters: $1 $2
}

function func2() # Short description
{
    echo func2 parameters: $1 $2
}

function help() # Show a list of functions
{
    grep "^function" $0
}

if [ "_$1" = "_" ]; then
    help
else
    "$@"
fi

这是一个交互式演示:

$ my.sh 
function func1() # Short description
function func2() # Short description
function help() # Show a list of functions


$ my.sh help
function func1() # Short description
function func2() # Short description
function help() # Show a list of functions


$ my.sh func1 a b
func1 parameters: a b

$ my.sh func2 x y
func2 parameters: x y

如果您有不想出现在帮助中的“私有”功能,则省略“功能”部分:

my_private_function()
{
    # Do something
}
于 2010-04-15T00:14:26.293 回答
14

typeset -f返回带有函数体的函数,因此使用一个简单的 awk 脚本来提取函数名

f1 () { :; }
f2 () { :; }
f3 () { :; }
f4 () { :; }
help () {
    echo "functions available:"
    typeset -f | awk '/ \(\) $/ && !/^main / {print $1}'
}
main () { help; }
main

该脚本输出:

functions available:
f1
f2
f3
f4
help
于 2011-05-03T10:39:18.037 回答
5

您在没有参数的情况下调用此函数,它只吐出一个“空格”分隔的函数名称列表。


function script.functions () {
    local fncs=`declare -F -p | cut -d " " -f 3`; # Get function list
    echo $fncs; # not quoted here to create shell "argument list" of funcs.
}

要将函数加载到数组中:


declare MyVar=($(script.functions));

当然,常识表明在调用此函数之前尚未将其源化到当前文件中的任何函数都不会显示在列表中。

使列表只读并可导出到此脚本调用的其他脚本:


declare -rx MyVar=($(script.functions));

要将整个列表打印为换行符分隔:


printf "%s\n" "${MyVar[@]}";
于 2011-05-03T08:54:43.660 回答
1

最好的办法是创建一个数组(您正在使用 bash),其中包含您想要宣传的函数,并让您的帮助函数迭代并打印它们。

set单独调用将产生函数,但会产生完整的函数。你仍然需要解析以 () 结尾的东西来获得谚语符号

它也可能更理智地使用类似的东西getopt变成争论。但是,好吧,理智是相对的,你还没有发布代码:)--function-namefunction_name

您的另一个选择是创建一个可加载的 bash(的一个分支set)来完成此操作。老实说,我更喜欢在为此任务编写可加载项之前进行解析。

于 2010-04-13T15:32:00.993 回答