目前我正在做一些从bash执行的单元测试。单元测试在bash脚本中初始化、执行和清理。该脚本通常包含init()、execute()和cleanup()函数。但它们不是强制性的。我想测试它们是否有定义。

我以前通过greping和seding源代码做到了这一点,但这似乎是错误的。还有更优雅的方式吗?

编辑:下面这句话很有魔力:

fn_exists()
{
    LC_ALL=C type $1 | grep -q 'shell function'
}

当前回答

来自我对另一个答案的评论(当我回到这个页面时,我总是忽略这个答案)

$ fn_exists() { test x$(type -t $1) = xfunction; }
$ fn_exists func1 && echo yes || echo no
no
$ func1() { echo hi from func1; }
$ func1
hi from func1
$ fn_exists func1 && echo yes || echo no
yes

其他回答

内置bash命令声明有一个选项-F,显示所有定义的函数名。如果给出了name参数,它将显示这些函数中哪些存在,如果都存在,它将相应地设置状态:

$ fn_exists() { declare -F "$1" > /dev/null; }

$ unset f
$ fn_exists f && echo yes || echo no
no

$ f() { return; }
$ fn_exist f && echo yes || echo no
yes

这告诉你它是否存在,但不是说它是一个函数

fn_exists()
{
  type $1 >/dev/null 2>&1;
}

借鉴其他解决方案和评论,我得出了以下结论:

fn_exists() {
  # appended double quote is an ugly trick to make sure we do get a string -- if $1 is not a known command, type does not output anything
  [ `type -t $1`"" == 'function' ]
}

用作……

if ! fn_exists $FN; then
    echo "Hey, $FN does not exist ! Duh."
    exit 2
fi

它检查给定的参数是否是一个函数,并避免重定向和其他grepping。

可以在没有任何外部命令的情况下使用'type',但你必须调用它两次,所以它的速度仍然是'declare'版本的两倍:

test_function () {
        ! type -f $1 >/dev/null 2>&1 && type -t $1 >/dev/null 2>&1
}

加上这不能在POSIX sh中工作,所以它完全没有价值,除了作为琐事!

我特别喜欢Grégory Joseph的解决方案

但我对它做了一点修改,以克服“双引号丑陋的把戏”:

function is_executable()
{
    typeset TYPE_RESULT="`type -t $1`"

    if [ "$TYPE_RESULT" == 'function' ]; then
        return 0
    else
        return 1
    fi
}