방금 BusyBox와 같은 많은 종류의 라이브러리 스크립트를 만들었습니다. 그것에, 나는 다음 함수를 사용하여 그것이 공급되고 있는지 테스트합니다 ...
function isSourced () {
[[ "${FUNCNAME[1]}" == "source" ]] && return 0
return 1
}
Bash가 유지 관리하는 FUNCNAME 배열은 기본적으로 함수 호출 스택입니다. $FUNCNAME
(또는 ${FUNCNAME[0]}
)는 현재 실행중인 기능의 이름입니다. ${FUNCNAME[1]}
그것을 호출 한 함수의 이름 등입니다.
최상위 항목은 스크립트 자체에 대한 특별한 값입니다. 그것은 포함됩니다 ...
- 스크립트가 소스 인 경우 "source"라는 단어
- 스크립트가 실행 중이고 테스트가 함수 내에서 수행되는 경우 "main"이라는 단어
- ""(null) 스크립트가 실행 중이고 테스트가 함수 외부에서 수행되는 경우, 즉 스크립트 자체의 레벨에서 수행됩니다.
위의 함수는 실제로 스크립트 수준에서 호출 할 때만 작동합니다 (필요한 전부입니다). 배열 항목 번호가 잘못되어 다른 함수 내부에서 호출하면 실패합니다. 어디서나 작동하려면 스택의 최상위를 찾아 해당 값을 테스트해야합니다.
필요한 경우 "스택 상단"의 배열 항목 번호를 얻을 수 있습니다.
local _top_of_stack=$(( ${#FUNCNAME[@]} - 1 ))
${#FUNCNAME[@]}
배열의 항목 수입니다. 0부터 시작하는 배열로 1을 빼서 마지막 항목을 얻습니다.
이 세 함수는 파이썬과 유사한 함수 스택 추적을 생성하는 데 함께 사용 되며이 모든 기능이 어떻게 작동하는지 더 잘 알 수 있습니다 ...
function inspFnStack () {
local T+=" "
local _at=
local _text="\n"
local _top=$(inspFnStackTop)
local _fn=${FUNCNAME[1]}; [[ $_fn =~ source|main ]] || _fn+="()"
local i=_top; ((--i))
#
_text+="$i item function call stack for $_fn ...\n"
_text+="| L BASH_SOURCE{BASH_LINENO called from}.FUNCNAME \n"
_text+="| ---------------------------------------------------\n"
while (( $i > 0 ))
do
_text+="| $i ${T}$(inspFnStackItem $i)\n"
T+=" "
((--i))
done
#
printf "$_text\n"
#
return 0
}
function inspFnStackItem () {
local _i=$1
local _fn=${FUNCNAME[$_i]}; [[ $_fn =~ source|main ]] || _fn+="()"
local _at="${BASH_LINENO[$_i-1]}"; [[ $_at == 1 ]] && _at="trap"
local _item="${BASH_SOURCE[$_i]}{${_at}}.$_fn"
#
printf "%s" "$_item"
return 0
}
function inspFnStackTop () {
# top stack item is 1 less than length of FUNCNAME array stack
printf "%d\n" $(( ${#FUNCNAME[@]} - 1 ))
#
return 0
}
FUNCNAME, BASH_SOURCE 및 BASH_LINENO는 마치 3 차원 배열 인 것처럼 bash에 의해 유지 관리되는 3 개의 배열입니다.