如何判断一个函数是否存在于POSIXshell中?

How to determine whether a function exists in a POSIX shell?

这基本上是与 Determine if a function exists in bash, except that this time it's not aiming at Bash, but at a POSIX shell 相同的问题:

如何判断给定名称的shell函数是否存在?

type等典型内建中的none似乎是POSIX强制要求的,所以这件事更难甚至不可能。

POSIX(更准确地说是 X/Open Portability Guide) specify the type 命令。它没有说明 type 命令应该 return 说明参数是什么。但是,标准表示它通常标识操作数,因此 type 实现在传递函数名称时不太可能不在其回复中包含字符串 "function"。

这应该适用于大多数(如果不是全部)POSIX 兼容 shells:

isFunction()
{
    type "" | sed "s///" | grep -qwi function
} 

你也可以 运行 command -V 而不是 type 这里,对未指定的输出格式有相同的评论。我从不这样做,因为前者打字更短而且更容易记住。但是,如果您 运行 决定不包含 XSI(可能 posh)的 shell,即 shell 会破坏许多现有脚本的可移植性,那么这将是强制性的通过将它尝试遵守的实用程序限制为严格的 POSIX 集。

您可以在实施 2013 版 POSIX 的 shell 中为此使用 command,或者使用旧规范的用户可移植性实用程序选项:

isFunction() { 
  command -V "" 2>/dev/null | grep -qwi function
}

但是请注意,规范实际上并未规定命令输出的形式。它要求函数被如此标识,因此当且仅当请求的名称是函数时,输出很可能会包含单词 function,但不能严格保证。上面的解决方案很容易被愚弄(参见@jiliagre 的评论)。

规范的不同部分要求一个 type 命令做很多相同的事情(对未指定的输出格式有相同的警告)。奇怪的是,它没有被列为 shell 内置命令所需的命令之一,但正如信息说明所说,它几乎必须是一个才能按指定工作。

为了完整起见:可以使用 typecommand -V 而无需产生任何额外的子进程,例如 sedgrep(尽管您仍然需要为 $(type ...) 产生一个):

is_function() {
    case "$(type -- "" 2>/dev/null)" in
        *function*) return 0 ;;
    esac
    return 1
}