如何判断某个函数是否存在于 POSIX shell 中?

问题描述 投票:0回答:4

这与 确定 bash 中是否存在函数基本是同一个问题,只不过这次不是针对 Bash,而是针对 a POSIX shell:

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

似乎像

type
这样的典型内置函数都不是 POSIX 强制要求的,所以这个问题更加困难,甚至可能是不可能的。

function shell sh posix
4个回答
6
投票

为了完整起见:可以使用

type
command -V
而不产生任何额外的子进程,如
sed
grep
(尽管您仍然需要为
$(type ...)
产生一个子进程):

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

5
投票

POSIX(更准确地说是X/开放可移植性指南)指定type命令。它没有说明

type
命令应该返回什么来告诉参数是什么。然而,标准表示它通常标识操作数,因此
type
实现在传递函数名称时不太可能不在其回复中包含字符串“function”。

这应该适用于大多数(如果不是全部)符合 POSIX 的 shell:

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

您也可以在此处运行

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


4
投票

您可以在实现 2013 版 POSIX 的 shell 中使用

command
或旧规范的用户可移植性实用程序选项:

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

但是,请注意,规范实际上并未规定命令输出的形式。 它要求函数被如此识别,因此当且仅当请求的名称是函数时,输出很可能包含单词

function
,但不严格保证。上述解决方案很容易被愚弄(请参阅@jiliagre的评论)。

规范的不同部分要求使用

type
命令执行几乎相同的操作(对于未指定的输出格式具有相同的警告)。奇怪的是,它没有被列为 shell 内置命令之一,但正如信息注释所说,它几乎必须是一个才能按指定工作。


0
投票

在这些情况下,此处的其他答案将返回

foo
的误报:

  • /tmp/function/foo
    是可执行的,并且
    $PATH
    包括
    /tmp/function
  • alias foo='echo function'
    已运行

更稳健的方法如下:

is_function() {
    [ -n "$1" ] && [ "$(command -v -- "$1")" = "$1" ] || return 1
    [ "$(command -V -- "$1")" != "$(unset -f -- "$1"; command -V -- "$1" 2>/dev/null)" ]
}

第一行确保

$1
存在,并且不是
$PATH
中的别名或可执行文件。然后我们检查
command -V
的输出,尝试在子 shell 中取消设置名为
$1
的函数,然后再次检查
command -V
。如果输出不同,
$1
一定是一个函数。

© www.soinside.com 2019 - 2024. All rights reserved.