bash 判断函数是否存在于bash中
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/85880/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Determine if a function exists in bash
提问by terminus
Currently I'm doing some unit tests which are executed from bash. Unit tests are initialized, executed and cleaned up in a bash script. This script usualy contains an init(), execute() and cleanup() functions. But they are not mandatory. I'd like to test if they are or are not defined.
目前我正在做一些从 bash 执行的单元测试。单元测试在 bash 脚本中初始化、执行和清理。这个脚本通常包含一个 init()、execute() 和 cleanup() 函数。但它们不是强制性的。我想测试它们是否被定义。
I did this previously by greping and seding the source, but it seemed wrong. Is there a more elegant way to do this?
我之前是通过 grep 和 seding 源来做到这一点的,但这似乎是错误的。有没有更优雅的方法来做到这一点?
Edit: The following sniplet works like a charm:
编辑:以下 sniplet 就像一个魅力:
fn_exists()
{
LC_ALL=C type | grep -q 'shell function'
}
回答by JBB
I think you're looking for the 'type' command. It'll tell you whether something is a function, built-in function, external command, or just not defined. Example:
我认为您正在寻找“类型”命令。它会告诉您某些东西是函数、内置函数、外部命令还是未定义。例子:
$ 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
回答by Allan Wind
$ g() { return; }
$ declare -f g > /dev/null; echo $?
0
$ declare -f j > /dev/null; echo $?
1
回答by Orwellophile
If declare is 10x faster than test, this would seem the obvious answer.
如果声明比测试快 10 倍,这似乎是显而易见的答案。
Edit: Below, the -f
option is superfluous with BASH, feel free to leave it out. Personally, I have trouble remembering which option does which, so I just use both. -fshows functions, and -Fshows function names.
编辑:下面,该-f
选项对于 BASH 来说是多余的,请随意将其省略。就个人而言,我很难记住哪个选项执行哪个,所以我只使用两者。 -f显示函数,-F显示函数名称。
#!/bin/sh
function_exists() {
declare -f -F > /dev/null
return $?
}
function_exists function_name && echo Exists || echo No such function
The "-F" option to declare causes it to only return the name of the found function, rather than the entire contents.
声明的“-F”选项使其仅返回找到的函数的名称,而不是整个内容。
There shouldn't be any measurable performance penalty for using /dev/null, and if it worries you that much:
使用 /dev/null 不应该有任何可衡量的性能损失,如果它让您如此担心:
fname=`declare -f -F `
[ -n "$fname" ] && echo Declare -f says $fname exists || echo Declare -f says does not exist
Or combine the two, for your own pointless enjoyment. They both work.
或者将两者结合起来,为您自己的无意义享受。他们都工作。
fname=`declare -f -F `
errorlevel=$?
(( ! errorlevel )) && echo Errorlevel says exists || echo Errorlevel says does not exist
[ -n "$fname" ] && echo Declare -f says $fname exists || echo Declare -f says does not exist
回答by Grégory Joseph
Borrowing from other solutions and comments, I came up with this:
借鉴其他解决方案和评论,我想出了这个:
fn_exists() {
# appended double quote is an ugly trick to make sure we do get a string -- if is not a known command, type does not output anything
[ `type -t `"" == 'function' ]
}
Used as ...
用作...
if ! fn_exists $FN; then
echo "Hey, $FN does not exist ! Duh."
exit 2
fi
It checks if the given argument is a function, and avoids redirections and other grepping.
它检查给定的参数是否是一个函数,并避免重定向和其他 grepping。
回答by jonathanserafini
Dredging up an old post ... but I recently had use of this and tested both alternatives described with :
挖出一个旧帖子......但我最近使用了这个并测试了用以下描述的两种替代方案:
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
this generated :
这产生了:
real 0m0.064s
user 0m0.040s
sys 0m0.020s
type
real 0m2.769s
user 0m1.620s
sys 0m1.130s
declare is a helluvalot faster !
声明速度更快!
回答by jarno
Testing different solutions:
测试不同的解决方案:
#!/bin/bash
test_declare () {
declare -f f > /dev/null
}
test_declare2 () {
declare -F f > /dev/null
}
test_type () {
type -t f | grep -q 'function'
}
test_type2 () {
[[ $(type -t f) = function ]]
}
funcs=(test_declare test_declare2 test_type test_type2)
test () {
for i in $(seq 1 1000); do ; done
}
f () {
echo 'This is a test function.'
echo 'This has more than one command.'
return 0
}
post='(f is function)'
for j in 1 2 3; do
for func in ${funcs[@]}; do
echo $func $post
time test $func
echo exit code $?; echo
done
case $j in
1) unset -f f
post='(f unset)'
;;
2) f='string'
post='(f is string)'
;;
esac
done
outputs e.g.:
输出例如:
test_declare (f is function)
real 0m0,055s user 0m0,041s sys 0m0,004s exit code 0
test_declare2 (f is function)
real 0m0,042s user 0m0,022s sys 0m0,017s exit code 0
test_type (f is function)
real 0m2,200s user 0m1,619s sys 0m1,008s exit code 0
test_type2 (f is function)
real 0m0,746s user 0m0,534s sys 0m0,237s exit code 0
test_declare (f unset)
real 0m0,040s user 0m0,029s sys 0m0,010s exit code 1
test_declare2 (f unset)
real 0m0,038s user 0m0,038s sys 0m0,000s exit code 1
test_type (f unset)
real 0m2,438s user 0m1,678s sys 0m1,045s exit code 1
test_type2 (f unset)
real 0m0,805s user 0m0,541s sys 0m0,274s exit code 1
test_declare (f is string)
real 0m0,043s user 0m0,034s sys 0m0,007s exit code 1
test_declare2 (f is string)
real 0m0,039s user 0m0,035s sys 0m0,003s exit code 1
test_type (f is string)
real 0m2,394s user 0m1,679s sys 0m1,035s exit code 1
test_type2 (f is string)
real 0m0,851s user 0m0,554s sys 0m0,294s exit code 1
test_declare (f 是函数)
真实 0m0,055s 用户 0m0,041s sys 0m0,004s 退出代码 0
test_declare2(f 是函数)
真实 0m0,042s 用户 0m0,022s sys 0m0,017s 退出代码 0
test_type (f 是函数)
真正的 0m2,200s 用户 0m1,619s sys 0m1,008s 退出代码 0
test_type2(f 是函数)
真实 0m0,746s 用户 0m0,534s sys 0m0,237s 退出代码 0
test_declare (f 未设置)
真正的 0m0,040s 用户 0m0,029s sys 0m0,010s 退出代码 1
test_declare2 (f 未设置)
真实 0m0,038s 用户 0m0,038s sys 0m0,000s 退出代码 1
test_type (f 未设置)
真实 0m2,438s 用户 0m1,678s sys 0m1,045s 退出代码 1
test_type2 (f 未设置)
真实 0m0,805s 用户 0m0,541s sys 0m0,274s 退出代码 1
test_declare (f 是字符串)
真实 0m0,043s 用户 0m0,034s sys 0m0,007s 退出代码 1
test_declare2(f 是字符串)
真实 0m0,039s 用户 0m0,035s sys 0m0,003s 退出代码 1
test_type (f 是字符串)
真实 0m2,394s 用户 0m1,679s sys 0m1,035s 退出代码 1
test_type2(f 是字符串)
真实 0m0,851s 用户 0m0,554s sys 0m0,294s 退出代码 1
So declare -F f
seems to be the best solution.
所以declare -F f
似乎是最好的解决方案。
回答by Scott
It boils down to using 'declare' to either check the output or exit code.
归结为使用“声明”来检查输出或退出代码。
Output style:
输出样式:
isFunction() { [[ "$(declare -Ff "")" ]]; }
Usage:
用法:
isFunction some_name && echo yes || echo no
However, if memory serves, redirecting to null is faster than output substitution (speaking of, the awful and out-dated `cmd` method should be banished and $(cmd) used instead.) And since declare returns true/false if found/not found, and functions return the exit code of the last command in the function so an explicit return is usually not necessary, and since checking the error code is faster than checking a string value (even a null string):
但是,如果内存可用,重定向到 null 比输出替换更快(说到,可怕和过时的 `cmd` 方法应该被放逐,而使用 $(cmd) 代替。)并且因为如果找到/,声明返回真/假/未找到,并且函数返回函数中最后一个命令的退出代码,因此通常不需要显式返回,并且因为检查错误代码比检查字符串值(甚至是空字符串)更快:
Exit status style:
退出状态样式:
isFunction() { declare -Ff "" >/dev/null; }
That's probably about as succinct and benign as you can get.
这可能是你所能得到的尽可能简洁和良性的。
回答by qneill
From my comment on another answer (which I keep missing when I come back to this page)
从我对另一个答案的评论(当我回到这个页面时我一直想念)
$ fn_exists() { test x$(type -t ) = xfunction; }
$ fn_exists func1 && echo yes || echo no
no
$ func1() { echo hi from func1; }
$ func1
hi from func1
$ fn_exists func1 && echo yes || echo no
yes
回答by Jonah
fn_exists()
{
[[ $(type -t ) == function ]] && return 0
}
update
更新
isFunc ()
{
[[ $(type -t ) == function ]]
}
$ isFunc isFunc
$ echo $?
0
$ isFunc dfgjhgljhk
$ echo $?
1
$ isFunc psgrep && echo yay
yay
$
回答by b1r3k
I particularly liked solution from Grégory Joseph
我特别喜欢Grégory Joseph 的解决方案
But I've modified it a little bit to overcome "double quote ugly trick":
但是我对其进行了一些修改以克服“双引号丑陋的技巧”:
function is_executable()
{
typeset TYPE_RESULT="`type -t `"
if [ "$TYPE_RESULT" == 'function' ]; then
return 0
else
return 1
fi
}