Programming

bash에 함수가 존재하는지 확인

procodes 2020. 5. 26. 21:19
반응형

bash에 함수가 존재하는지 확인


현재 bash에서 실행되는 단위 테스트를 수행하고 있습니다. 단위 테스트는 bash 스크립트에서 초기화, 실행 및 정리됩니다. 이 스크립트는 보통 init (), execute () 및 cleanup () 함수를 포함합니다. 그러나 필수 사항은 아닙니다. 그것들이 정의되어 있는지 여부를 테스트하고 싶습니다.

나는 이전에 소스를 greping하고 seding 하여이 작업을 수행했지만 잘못된 것 같습니다. 더 우아한 방법이 있습니까?

편집 : 다음 코드는 매력처럼 작동합니다.

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

나는 당신이 '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

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

선언이 테스트보다 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

다른 솔루션과 의견을 빌려서, 나는 이것을 생각해 냈습니다.

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을 피합니다.


오래된 게시물을 준공 ...하지만 최근에 이것을 사용하고 다음과 같이 설명 된 두 가지 대안을 테스트했습니다.

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 더 빠릅니다!


출력 또는 종료 코드를 확인하기 위해 'declare'을 사용하는 것으로 요약됩니다.

출력 스타일 :

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

용법:

isFunction some_name && echo yes || echo no

그러나 메모리가 제공되는 경우 null로 리디렉션하는 것이 출력 대체보다 빠릅니다 (즉, 끔찍하고 오래된`cmd` 메소드를 삭제하고 대신 $ (cmd)를 사용해야 함). 선언이 발견되면 true / false를 반환합니다. 찾을 수없고 함수는 함수에서 마지막 명령의 종료 코드를 반환하므로 일반적으로 명시적인 반환이 필요하지 않으며 오류 코드를 확인하는 것이 문자열 값 (널 문자열도 확인)보다 빠르기 때문에 :

종료 상태 스타일 :

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

그것은 아마도 당신이 얻을 수있는 간결하고 양성에 관한 것입니다.


다른 솔루션 테스트 :

#!/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는 함수 임)

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

So declare -F f seems to be the best solution.


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

update

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

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

From my comment on another answer (which I keep missing when I come back to this page)

$ fn_exists() { test x$(type -t $1) = 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

This tells you if it exists, but not that it's a function

fn_exists()
{
  type $1 >/dev/null 2>&1;
}

I particularly liked solution from 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 $1`"

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

I would improve it to:

fn_exists()
{
    type $1 2>/dev/null | grep -q 'is a function'
}

And use it like this:

fn_exists test_function
if [ $? -eq 0 ]; then
    echo 'Function exists!'
else
    echo 'Function does not exist...'
fi

It is possible to use 'type' without any external commands, but you have to call it twice, so it still ends up about twice as slow as the 'declare' version:

test_function () {
        ! type -f $1 >/dev/null 2>&1 && type -t $1 >/dev/null 2>&1
}

Plus this doesn't work in POSIX sh, so it's totally worthless except as trivia!

참고URL : https://stackoverflow.com/questions/85880/determine-if-a-function-exists-in-bash

반응형