当前位置:  开发笔记 > 编程语言 > 正文

确定bash中是否存在函数

如何解决《确定bash中是否存在函数》经验,为你挑选了7个好方法。

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

我之前通过greping和seding来源做了这个,但它似乎错了.有没有更优雅的方式来做到这一点?

编辑:以下代码片段就像一个魅力:

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

JBB.. 182

我想你正在寻找'type'命令.它会告诉你某些东西是函数,内置函数,外部命令还是未定义.例:

$ 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

`type -t $ function`是餐票. (114认同)

`type [-t]`很高兴*告诉你你是什么东西,但是当*测试*如果某个东西是一个函数时,它很慢,因为你必须管道grep或使用反引号,这两个都产生了一个子进程. (5认同)

你为什么不把它作为答案发布?:-) (4认同)

为什么不重写呢? (3认同)


Allan Wind.. 72

$ g() { return; }
$ declare -f g > /dev/null; echo $?
0
$ declare -f j > /dev/null; echo $?
1

实际上,它也可以在zsh(对rc脚本有用)中工作,并且不需要grep作为类型。 (2认同)


Orwellophile.. 36

如果声明比测试快10倍,这似乎是明显的答案.

编辑:下面,-f选项是多余的BASH,随意留下它.就个人而言,我无法记住哪个选项可以做到,所以我只使用它们. -f显示函数,-F显示函数名称.

#!/bin/sh

function_exists() {
    declare -f -F $1 > /dev/null
    return $?
}

function_exists function_name && echo Exists || echo No such function

声明的"-F"选项使其仅返回找到的函数的名称,而不是整个内容.

使用/ dev/null不应该有任何可衡量的性能损失,如果它让你担心的那么多:

fname=`declare -f -F $1`
[ -n "$fname" ]    && echo Declare -f says $fname exists || echo Declare -f says $1 does not exist

或者将两者结合起来,为自己的无意义享受.他们都工作.

fname=`declare -f -F $1`
errorlevel=$?
(( ! errorlevel )) && echo Errorlevel says $1 exists     || echo Errorlevel says $1 does not exist
[ -n "$fname" ]    && echo Declare -f says $fname exists || echo Declare -f says $1 does not exist

zsh中不存在`-F`选项des(对于可移植性很有用) (3认同)

'-f'选项是多余的. (2认同)


Grégory Jose.. 18

借鉴其他解决方案和评论,我想出了这个:

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.



1> JBB..:

我想你正在寻找'type'命令.它会告诉你某些东西是函数,内置函数,外部命令还是未定义.例:

$ 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


`type -t $ function`是餐票.
`type [-t]`很高兴*告诉你你是什么东西,但是当*测试*如果某个东西是一个函数时,它很慢,因为你必须管道grep或使用反引号,这两个都产生了一个子进程.
你为什么不把它作为答案发布?:-)
为什么不重写呢?

2> Allan Wind..:
$ g() { return; }
$ declare -f g > /dev/null; echo $?
0
$ declare -f j > /dev/null; echo $?
1


实际上,它也可以在zsh(对rc脚本有用)中工作,并且不需要grep作为类型。

3> Orwellophile..:

如果声明比测试快10倍,这似乎是明显的答案.

编辑:下面,-f选项是多余的BASH,随意留下它.就个人而言,我无法记住哪个选项可以做到,所以我只使用它们. -f显示函数,-F显示函数名称.

#!/bin/sh

function_exists() {
    declare -f -F $1 > /dev/null
    return $?
}

function_exists function_name && echo Exists || echo No such function

声明的"-F"选项使其仅返回找到的函数的名称,而不是整个内容.

使用/ dev/null不应该有任何可衡量的性能损失,如果它让你担心的那么多:

fname=`declare -f -F $1`
[ -n "$fname" ]    && echo Declare -f says $fname exists || echo Declare -f says $1 does not exist

或者将两者结合起来,为自己的无意义享受.他们都工作.

fname=`declare -f -F $1`
errorlevel=$?
(( ! errorlevel )) && echo Errorlevel says $1 exists     || echo Errorlevel says $1 does not exist
[ -n "$fname" ]    && echo Declare -f says $fname exists || echo Declare -f says $1 does not exist


zsh中不存在`-F`选项des(对于可移植性很有用)
'-f'选项是多余的.

4> Grégory Jose..:

借鉴其他解决方案和评论,我想出了这个:

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.


你正在使用bash,使用`[[...]]`而不是`[...]`并删除引用黑客.也是反铲,这很慢.请改用`declare -f $ 1>/dev/null`.
使用空参数避免错误,减少引号,并使用'='posix兼容等式,它可以安全地减少到::`fn_exists(){[x $(type -t $ 1)= xfunction]; }`

5> 小智..:

挖掘一个旧帖子......但我最近使用了这个并测试了两种替代方案:

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

声明是一个helluvalot更快!


当然,因为你没有在第一个中调用grep.

6> 小智..:

归结为使用'declare'来检查输出或退出代码.

输出方式:

isFunction() { [[ "$(declare -Ff "$1")" ]]; }

用法:

isFunction some_name && echo yes || echo no

但是,如果内存服务,重定向到null比输出替换更快(说起来,应该放弃可怕的和过时的`cmd`方法并使用$(cmd).)并且因为声明如果找到则返回true/false /找不到,函数返回函数中最后一个命令的退出代码,因此通常不需要显式返回,因为检查错误代码比检查字符串值(甚至是空字符串)要快:

退出状态样式:

isFunction() { declare -Ff "$1" >/dev/null; }

这可能就像你能得到的那样简洁和温和.


为了获得最大的简洁性,请使用`isFunction(){declare -F"$ 1"; }>& - `
isFunction(){声明-F-“ $ @”> / dev / null; }`是我的推荐。它也适用于名称列表(仅在全部为函数时才成功),以-开头的名称没有问题,而在我这一边(bash 4.2.25),当输出为用`>&-`关闭,因为在这种情况下它无法将名称写入stdout

7> jarno..:

测试不同的解决方案:

#!/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 $1; 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

输出例如:

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(未设置)

实数0m0,040s用户0m0,029s sys 0m0,010s退出代码1

test_declare2(未设置)

实际0m0,038s用户0m0,038s sys 0m0,000s退出代码1

test_type(未设置)

实际0m2,438s用户0m1,678s sys 0m1,045s退出代码1

test_type2(未设置)

实际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

因此,declare -F f似乎是最好的解决方案。

推荐阅读
Gbom2402851125
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有