bash에 함수가 존재하는지 확인합니다.
저는 현재 bash에서 실행되는 몇 가지 유닛 테스트를 하고 있습니다.유닛 테스트는 bash 스크립트로 초기화, 실행 및 청소됩니다.이 스크립트에는 보통 init(), execute() 및 cleanup() 함수가 포함됩니다.하지만 그것들은 의무사항이 아니다.정의되어 있는지 없는지를 테스트하고 싶습니다.
나는 이전에 소스를 greping하고 seeding을 해서 이것을 했지만, 그것은 잘못된 것 같았다.좀 더 우아한 방법이 있을까요?
편집: 다음 스니펫은 마법처럼 작동합니다.
fn_exists()
{
LC_ALL=C type $1 | grep -q 'shell function'
}
하다, 하다, 하다, 하다.[[ $(type -t foo) == function ]] && echo "Foo exists"
★★★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
builtin bash " "declare이 -F이치인수를 중 함수가 존재하는지 되며, 하는 경우 같이 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
$ 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
선언이 테스트보다 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
지정된 인수가 함수인지 확인하고 리다이렉션 및 기타 그리핑을 회피합니다.
오래된 포스트를 준설하고 있습니다.다만, 최근 이것을 사용해, 에 기재되어 있는 양쪽의 대안을 테스트했습니다.
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
declarate is helluvalot fast!
다양한 솔루션 테스트:
#!/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_function(f는 함수)
real 0m0,055s 사용자 0m0,041s sys 0m0,004s 종료 코드 0
test_param2(f는 함수)
real 0m0,042s 사용자 0m0,022s 시스템 0m0,017s 종료 코드 0
test_type(f는 함수)
real 0m2,200s 사용자 0m1,619s 시스템 0m1,008s 종료 코드 0
test_type2(f는 함수)
real 0m0,746s 사용자 0m0,534s 시스템 0m0,237s 종료 코드 0
test_module(설정 해제)
real 0m0,040s 사용자 0m0,029s 시스템 0m0,010s 종료 코드1
test_param2(설정 해제)
real 0m0,038s 사용자 0m0,038s sys 0m0,000s 종료 코드 1
test_type(설정 해제)
real 0m2,438s 사용자 0m1,678s sys 0m1,045s 종료 코드1
test_type2(설정 해제)
real 0m0,805s 사용자 0m0,541s 시스템 0m0,274s 종료 코드 1
test_module(f는 문자열)
real 0m0,043s 사용자 0m0,034s sys 0m0,007s 종료 코드 1
test_param2(f는 문자열)
real 0m0,039s 사용자 0m0,035s sys 0m0,003s 종료 코드 1
test_type(f는 문자열)
real 0m2,394s 사용자 0m1,679s 시스템 0m1,035s 종료 코드 1
test_type2(f는 문자열)
real 0m0,851s 사용자 0m0,554s sys 0m0,294s 종료 코드1
그렇게declare -F f가장 좋은 해결책인 것 같습니다.
요약하면 'declare'를 사용하여 출력을 확인하거나 코드를 종료하는 것입니다.
출력 스타일:
isFunction() { [[ "$(declare -Ff "$1")" ]]; }
사용방법:
isFunction some_name && echo yes || echo no
다만, 메모리가 기능하는 경우는, 출력 치환보다 null로 리다이렉트 하는 것이 고속입니다(「cmd」메서드는 삭제해, 대신에 $(cmd)를 사용할 필요가 있습니다).또한 declate는 true/false를 반환하고 함수는 함수의 마지막 명령어 종료 코드를 반환하기 때문에 일반적으로 명시적인 반환은 필요하지 않으며 오류 코드를 확인하는 것이 문자열 값(늘 문자열도 마찬가지)을 확인하는 것보다 빠릅니다.
종료 상태 스타일:
isFunction() { declare -Ff "$1" >/dev/null; }
그것은 아마도 당신이 얻을 수 있는 한 간결하고 양성적일 것이다.
다른 답변에 대한 제 코멘트(이 페이지로 돌아오면 계속 놓치고 있습니다)
$ 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
함수의 호출(정의되어 있는 경우).
기존 함수 이름.예를 들어 이름이my_function, 그 후 를 사용합니다.
[[ "$(type -t my_function)" == 'function' ]] && my_function;
# or
[[ "$(declare -fF my_function)" ]] && my_function;
함수의 이름은 변수에 저장됩니다.선언하면func=my_function, 그럼 을 사용할 수 있습니다.
[[ "$(type -t $func)" == 'function' ]] && $func;
# or
[[ "$(declare -fF $func)" ]] && $func;
같은 결과가||대신&&
(이러한 논리 반전은 코딩 중에 도움이 될 수 있습니다.)
[[ "$(type -t my_function)" != 'function' ]] || my_function;
[[ ! "$(declare -fF my_function)" ]] || my_function;
func=my_function
[[ "$(type -t $func)" != 'function' ]] || $func;
[[ ! "$(declare -fF $func)" ]] || $func;
엄격한 모드 및 사전 조건 체크
우리는 가지고 있다.set -e엄밀한 모드입니다.
사용하고 있습니다|| return전제로 기능하고 있습니다.
이로 인해 셸 프로세스가 강제로 종료됩니다.
# Set a strict mode for script execution. The essence here is "-e"
set -euf +x -o pipefail
function run_if_exists(){
my_function=$1
[[ "$(type -t $my_function)" == 'function' ]] || return;
$my_function
}
run_if_exists non_existing_function
echo "you will never reach this code"
상기의 내용은 다음과 같습니다.
set -e
function run_if_exists(){
return 1;
}
run_if_exists
프로세스가 중단됩니다.
사용하다|| { true; return; }대신|| return;이 문제를 해결하기 위한 전제조건에서요
[[ "$(type -t my_function)" == 'function' ]] || { true; return; }
이것은 그것이 존재하는지 알 수 있지만 함수는 아니다.
fn_exists()
{
type $1 >/dev/null 2>&1;
}
하지만 "추악한 이중 따옴표"를 극복하기 위해 조금 수정했습니다.
function is_executable()
{
typeset TYPE_RESULT="`type -t $1`"
if [ "$TYPE_RESULT" == 'function' ]; then
return 0
else
return 1
fi
}
fn_exists()
{
[[ $(type -t $1) == function ]] && return 0
}
갱신하다
isFunc ()
{
[[ $(type -t $1) == function ]]
}
$ isFunc isFunc
$ echo $?
0
$ isFunc dfgjhgljhk
$ echo $?
1
$ isFunc psgrep && echo yay
yay
$
다음과 같이 개선하겠습니다.
fn_exists()
{
type $1 2>/dev/null | grep -q 'is a function'
}
그리고 이렇게 사용하세요.
fn_exists test_function
if [ $? -eq 0 ]; then
echo 'Function exists!'
else
echo 'Function does not exist...'
fi
외부 명령 없이 'type'을 사용할 수 있지만 두 번 호출해야 하므로 'declare' 버전보다 속도가 두 배 정도 느려집니다.
test_function () {
! type -f $1 >/dev/null 2>&1 && type -t $1 >/dev/null 2>&1
}
게다가 이것은 POSIX sh에서는 동작하지 않기 때문에, 하찮은 것 이외에는 전혀 가치가 없습니다.
4가지 방법으로 확인할 수 있습니다.
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'; }
언급URL : https://stackoverflow.com/questions/85880/determine-if-a-function-exists-in-bash
'codememo' 카테고리의 다른 글
| SQL-Server에 퍼센트 값을 저장하는 가장 좋은 방법은 무엇입니까? (0) | 2023.04.18 |
|---|---|
| 셀에서 복사할 때 따옴표 생략 (0) | 2023.04.18 |
| Bash의 마지막 명령어 출력 재사용 (0) | 2023.04.18 |
| 어플리케이션의 기능은 정확히 무엇입니까?Excel의 CutCopyMode 속성 (0) | 2023.04.13 |
| 태스크바에 표시되는 응용 프로그램 아이콘을 할당하는 방법 (0) | 2023.04.13 |