仅当它是 bash 函数时才执行

仅当它是 bash 函数时才执行

我正在寻找类似于 Bash 内置的东西,command如果它是一个函数,它只会运行一些东西。所以目前我有一种不安全的做法:

# Go through arguments in order
for i in $*; do
    if [ -z `which $i` ]; then
        # Run function
        $i && echo -n ' '
    fi
done

这个 if 语句不能正常工作。无论如何,即使我可以检查它是否是命令而不是函数,我也无法显式运行函数,这很糟糕,因为如果有人在 $PATH 中有任何与我的函数同名的程序,它们将被跑步。如果我取消 PATH 或将其设置为其他任何内容,任何人仍然可以使用 $i 显式运行程序,所以这也不是解决方案。

有什么办法可以“保护”我的 shell 脚本吗?

答案1

使用bash,您可以执行以下操作:

for f do
  if declare -F -- "$f" >/dev/null 2>&1; then
    : "$f" is a function, do something with it
  fi
done

declare -F -- "$f" >/dev/null 2>&1$f如果是 bash 函数,将返回成功代码,不输出任何内容。

bash在POSIX 模式下运行时,您可能还想通过添加builtin enable -n -- "$f".

答案2

Bash 提供的正式方法是使用type内置的 as of type -t

function fun() {
  : foo bar
}

if [ function = $(type -t fun) ]; then
  echo fun is a function.
fi

如果您对参数列表中的函数名称有疑问,只需用双引号引起来即可:$(type -t "$arg")

答案3

虽然您可能已经在bashshell 中设置好了,但要进行类似的可移植操作,您可能会使用类似以下的内容......

eval "  for c in $(unalias -a
        for c do case ${c#function}  in
                (*[!_[:alnum:]]*) ;; (?*)
                PATH=   command -v "$c" >&2 &&
                PATH=   command -V "$c"     &&
                        printf '\n'"'$c'"'\\\0'
        esac 2>/dev/null; done  |
        tr  '\t\n\0' '  \n'     |
        sed -ne's/.* function .* / /p')"'
;do     "$c"; printf %02s
done'

它分阶段进行:

  1. 首先清除所有包含任何字符的参数,这些字符可能会使它们首先失去作为 shell 名称的资格。
  2. 如果当前 arg 是有效名称有效的 shell 内置函数或函数将其名称和类型打印到标准输出。由于 shell 可以改变其输出的方式,因此command -V不能将其输出视为一行。因此,输出后面带有我们验证的名称和空字节。
  3. tr将所有换行符和制表符转换为空格,并将所有空字节转换为换行符。
  4. ,替换掉所有行中最后一个空格字符,如果该行也与字符串匹配则打印sed结果s///function
  5. 所有 的sed输出都作为外循环的迭代器向上舍入for,每个迭代器依次执行,并且在每个执行后printf写出两个空格。

相关内容