判断 Bash 中是否存在一个函数。

247

目前我正在进行一些从bash执行的单元测试。单元测试在bash脚本中初始化、执行和清理。这个脚本通常包含一个init()、execute()和cleanup()函数,但它们不是必需的。我想测试它们是否被定义。

我之前通过grep和sed源代码来实现这个功能,但感觉不太对。有没有更优雅的方法?

编辑:下面的代码片段非常好用:

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

谢谢。我使用这个来有条件地定义存根函数版本,当加载一个 shell 库时。fn_exists foo || foo() { :; } - Harvey
3
通过使用type -t==,您可以简化grep的命令。 - Roland Weber
1
当地区设置为非英语时无法正常工作。在使用芬兰语区域设置时,“type test_function”会显示“test_function on funktio。”而在使用德语区域设置时,则会显示“ist eine Funktion”。 - Kimmo Lehto
4
对于非英语的区域设置,使用LC_ALL=C来解决问题。 - gaRex
15个回答

3

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

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

3

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

但我稍微修改了一下,以克服“双引号丑陋技巧”的问题:

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

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

他的原始解决方案应该可以工作,如果他将 type 调用放在引号内。 - akostadinov

2

你可以用4种方式来检查它们

fn_exists() { type -t $1 >/dev/null && echo 'exists'; }
fn_exists() { declare -F $1 >/dev/null && echo 'exists'; }
fn_exists() { typeset -F $1 >/dev/null && echo 'exists'; }
fn_exists() { compgen -A function $1 >/dev/null && echo 'exists'; }

所有这些之间有什么区别? - bfontaine

2
我会将其改进为:

我会进行改进:

fn_exists()
{
    type $1 2>/dev/null | grep -q 'is a function'
}

使用方法如下:

fn_exists test_function
if [ $? -eq 0 ]; then
    echo 'Function exists!'
else
    echo 'Function does not exist...'
fi

1

可以使用'type'而不需要任何外部命令,但是你必须调用它两次,所以它仍然比 'declare' 版本慢大约两倍:

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

此外,这在 POSIX sh 中不起作用,因此除了作为琐事外毫无价值!


test_type_nogrep(){a(){echo' a';}; local b = $(type a); c = $ {b // is a function /}; [ $?= 0] &&返回1 ||返回0; } - qneill - Alexx Roche

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接