21

如何确定某个函数是否已在 bash 脚本中定义?

我正在尝试使我的 .bash_login 脚本在系统之间可移植,因此我想添加逻辑以仅在函数存在时才调用它。

仅当该系统上存在该功能时,我__git_ps1()才想添加。PS1这个函数通常在git-completion.bashgit 源中定义,或者由 ports/apt 安装的 bash 完成脚本之一定义。

4

9 回答 9

19

我意识到这是一个老问题,但没有其他答案能像我想要的那样简单。这使用type -t(如 Chen Levy 的评论中所建议的)作为一种有效的测试类型,但随后使用 shell 字符串比较而不是调用 grep。

if [ "$(type -t somefunc)" = 'function' ]; then
    somefunc arg1 arg2
fi

更进一步,它也间接地起作用:

funcname=do_it_special_$somehow
if [ "$(type -t $funcname)" != 'function' ]; then
    funcname=do_it_normal
fi
$funcname arg1 arg2
于 2011-09-13T22:07:48.167 回答
11
if type __git_ps1 | grep -q '^function$' 2>/dev/null; then
    PS1=whatever
fi
于 2009-06-17T15:00:56.153 回答
8

您可以使用:

type function_name

in 将返回您的函数定义,以防它存在。因此,您可以检查输出是否为空。

PS。更好的是,我刚刚检查过它将输出该函数不存在,否则输出函数体。

于 2009-06-17T15:00:16.793 回答
6

如果您需要/bin/sh兼容的版本,则不能使用typesetdeclare测试函数定义,因为它不是内置的 shell。此外,在某些系统上可能不提供该-f选项。type

我提出的解决方案已经部分包含在其他答案中:

isFunction() {
  type $1 | head -1 | egrep "^$1.*function\$" >/dev/null 2>&1;
  return;
}

isFunction __git_ps1 && PS1=__git_ps1
于 2011-11-08T11:55:35.813 回答
5

声明 -F 'function_name' > /dev/null

回声$?

美元?如果函数存在,则结果值为 0,否则为 1

于 2009-06-17T15:02:12.530 回答
3

我认为最好使用声明,即使它比类型稍慢。还为 PATH 中的别名或脚本键入 suceeds。

我正在使用这个:

function function_exists
{
    FUNCTION_NAME=$1

    [ -z "$FUNCTION_NAME" ] && return 1

    declare -F "$FUNCTION_NAME" > /dev/null 2>&1

    return $?
}

所以稍后在我的脚本中,我可以很容易地看到发生了什么:

if function_exists __git_ps1
then
    PS1=__git_ps1
fi

甚至是仍然可读的单行:

function_exists __git_ps1 && PS1=__git_ps1
于 2009-07-28T20:52:12.363 回答
1

您可以列出所有可用的函数或使用 compgen 检查单个函数:

help compgen

compgen -A function

compgen -A function myfunc 1>/dev/null && echo 'myfunc already exists' || exit 1
于 2011-04-05T13:25:34.613 回答
0
if declare -F | grep __git_ps1$
then
    PS1=whatever
fi
于 2009-06-17T15:11:41.123 回答
0

请注意,busybox(极简的多合一 shell 实现,例如在 Windows 上很有用)具有“type”但“type -t”打印错误的内容,所以我只检查 type 的返回值以查看是否有可调用的内容。busybox 也没有声明。

于 2012-05-31T16:30:04.087 回答