目前我正在做一些从bash执行的单元测试。单元测试在bash脚本中初始化、执行和清理。该脚本通常包含init()、execute()和cleanup()函数。但它们不是强制性的。我想测试它们是否有定义。
我以前通过greping和seding源代码做到了这一点,但这似乎是错误的。还有更优雅的方式吗?
编辑:下面这句话很有魔力:
fn_exists()
{
LC_ALL=C type $1 | grep -q 'shell function'
}
目前我正在做一些从bash执行的单元测试。单元测试在bash脚本中初始化、执行和清理。该脚本通常包含init()、execute()和cleanup()函数。但它们不是强制性的。我想测试它们是否有定义。
我以前通过greping和seding源代码做到了这一点,但这似乎是错误的。还有更优雅的方式吗?
编辑:下面这句话很有魔力:
fn_exists()
{
LC_ALL=C type $1 | grep -q 'shell function'
}
当前回答
你可以用四种方法检查它们
fn_exists() { type -t $1 >/dev/null && echo 'exists'; }
fn_exists() { declare -F $1 >/dev/null && echo 'exists'; }
fn_exists() { typeset -F $1 >/dev/null && echo 'exists'; }
fn_exists() { compgen -A function $1 >/dev/null && echo 'exists'; }
其他回答
可以在没有任何外部命令的情况下使用'type',但你必须调用它两次,所以它的速度仍然是'declare'版本的两倍:
test_function () {
! type -f $1 >/dev/null 2>&1 && type -t $1 >/dev/null 2>&1
}
加上这不能在POSIX sh中工作,所以它完全没有价值,除了作为琐事!
内置bash命令声明有一个选项-F,显示所有定义的函数名。如果给出了name参数,它将显示这些函数中哪些存在,如果都存在,它将相应地设置状态:
$ fn_exists() { declare -F "$1" > /dev/null; }
$ unset f
$ fn_exists f && echo yes || echo no
no
$ f() { return; }
$ fn_exist f && echo yes || echo no
yes
像这样:[[$(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
挖掘一根旧柱子……但我最近使用了这个方法,并测试了以下两种替代方法:
test_declare () {
a () { echo 'a' ;}
declare -f a > /dev/null
}
test_type () {
a () { echo 'a' ;}
type a | grep -q 'is a function'
}
echo 'declare'
time for i in $(seq 1 1000); do test_declare; done
echo 'type'
time for i in $(seq 1 100); do test_type; done
这产生了:
real 0m0.064s
user 0m0.040s
sys 0m0.020s
type
real 0m2.769s
user 0m1.620s
sys 0m1.130s
声明要快得多!
它可以归结为使用“declare”来检查输出或退出代码。
输出方式:
isFunction() { [[ "$(declare -Ff "$1")" ]]; }
用法:
isFunction some_name && echo yes || echo no
然而,如果内存有用,重定向到null比输出替换更快(说到这里,可怕的过时的' cmd '方法应该被摒弃,取而代之的是$(cmd)。)由于declare在找到/未找到时返回true/false,并且函数返回函数中最后一个命令的退出码,因此通常不需要显式返回,并且由于检查错误代码比检查字符串值(甚至是空字符串)更快:
退出状态样式:
isFunction() { declare -Ff "$1" >/dev/null; }
这可能是你能得到的最简洁和最温和的说法了。