目前我正在做一些从bash执行的单元测试。单元测试在bash脚本中初始化、执行和清理。该脚本通常包含init()、execute()和cleanup()函数。但它们不是强制性的。我想测试它们是否有定义。

我以前通过greping和seding源代码做到了这一点,但这似乎是错误的。还有更优雅的方式吗?

编辑:下面这句话很有魔力:

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

当前回答

函数的调用(如果已定义)。

已知函数名。假设名称是my_function,然后使用

[[ "$(type -t my_function)" == 'function' ]] && my_function;
# or
[[ "$(declare -fF my_function)" ]] && my_function;

函数名存储在一个变量中。如果我们声明func=my_function,那么我们可以使用

[[ "$(type -t $func)" == 'function' ]] && $func;
# or
[[ "$(declare -fF $func)" ]] && $func;

||代替&&也有同样的结果 (这样的逻辑反转在编码过程中很有用)

[[ "$(type -t my_function)" != 'function' ]] || my_function;
[[ ! "$(declare -fF my_function)" ]] || my_function;

func=my_function
[[ "$(type -t $func)" != 'function' ]] || $func;
[[ ! "$(declare -fF $func)" ]] || $func;

严格的模式和前提条件检查 我们将-e设置为严格模式。 在先决条件下,我们在函数中使用|| return。 这将迫使我们的shell进程终止。

# Set a strict mode for script execution. The essence here is "-e"
set -euf +x -o pipefail

function run_if_exists(){
    my_function=$1

    [[ "$(type -t $my_function)" == 'function' ]] || return;

    $my_function
}

run_if_exists  non_existing_function
echo "you will never reach this code"

以上是等价的

set -e
function run_if_exists(){
    return 1;
}
run_if_exists

这会终止您的流程。 使用|| {true;返回;}而不是||返回;在前提条件下解决这个问题。

    [[ "$(type -t my_function)" == 'function' ]] || { true; return; }

其他回答

fn_exists()
{
   [[ $(type -t $1) == function ]] && return 0
}

更新

isFunc () 
{ 
    [[ $(type -t $1) == function ]]
}

$ isFunc isFunc
$ echo $?
0
$ isFunc dfgjhgljhk
$ echo $?
1
$ isFunc psgrep && echo yay
yay
$

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

但我对它做了一点修改,以克服“双引号丑陋的把戏”:

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

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

借鉴其他解决方案和评论,我得出了以下结论:

fn_exists() {
  # appended double quote is an ugly trick to make sure we do get a string -- if $1 is not a known command, type does not output anything
  [ `type -t $1`"" == 'function' ]
}

用作……

if ! fn_exists $FN; then
    echo "Hey, $FN does not exist ! Duh."
    exit 2
fi

它检查给定的参数是否是一个函数,并避免重定向和其他grepping。

像这样:[[$(type -t foo) == function]] && echo " foo存在"

内置类型命令将告诉您某个东西是函数、内置函数、外部命令还是没有定义。

附加的例子:

$ LC_ALL=C type foo
bash: type: foo: not found

$ LC_ALL=C type ls
ls is aliased to `ls --color=auto'

$ which type

$ LC_ALL=C type type
type is a shell builtin

$ LC_ALL=C type -t rvm
function

$ if [ -n "$(LC_ALL=C type -t rvm)" ] && [ "$(LC_ALL=C type -t rvm)" = function ]; then echo rvm is a function; else echo rvm is NOT a function; fi
rvm is a function

函数的调用(如果已定义)。

已知函数名。假设名称是my_function,然后使用

[[ "$(type -t my_function)" == 'function' ]] && my_function;
# or
[[ "$(declare -fF my_function)" ]] && my_function;

函数名存储在一个变量中。如果我们声明func=my_function,那么我们可以使用

[[ "$(type -t $func)" == 'function' ]] && $func;
# or
[[ "$(declare -fF $func)" ]] && $func;

||代替&&也有同样的结果 (这样的逻辑反转在编码过程中很有用)

[[ "$(type -t my_function)" != 'function' ]] || my_function;
[[ ! "$(declare -fF my_function)" ]] || my_function;

func=my_function
[[ "$(type -t $func)" != 'function' ]] || $func;
[[ ! "$(declare -fF $func)" ]] || $func;

严格的模式和前提条件检查 我们将-e设置为严格模式。 在先决条件下,我们在函数中使用|| return。 这将迫使我们的shell进程终止。

# Set a strict mode for script execution. The essence here is "-e"
set -euf +x -o pipefail

function run_if_exists(){
    my_function=$1

    [[ "$(type -t $my_function)" == 'function' ]] || return;

    $my_function
}

run_if_exists  non_existing_function
echo "you will never reach this code"

以上是等价的

set -e
function run_if_exists(){
    return 1;
}
run_if_exists

这会终止您的流程。 使用|| {true;返回;}而不是||返回;在前提条件下解决这个问题。

    [[ "$(type -t my_function)" == 'function' ]] || { true; return; }