[bash] 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는 함수 임)

실제 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 시스템 0m0,010s 종료 코드 1

test_declare2 (설정 해제)

실제 0m0,038s 사용자 0m0,038s sys 0m0,000s 종료 코드 1

test_type (f 설정 해제)

실제 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 시스템 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가장 좋은 해결책 인 것 같습니다.