Я щойно створив такий же бібліотечний сценарій, який працює дуже багато, як BusyBox. У ній я використовую наступну функцію, щоб перевірити, чи є її джерело ...
function isSourced () {
[[ "${FUNCNAME[1]}" == "source" ]] && return 0
return 1
}
Масив FUNCNAME, що підтримується Bash, по суті є стеком викликів функцій. $FUNCNAME(або ${FUNCNAME[0]}) - ім'я функції, що виконується в даний час.${FUNCNAME[1]}- це назва функції, яка її викликала тощо.
Найвищий елемент - це особливе значення для самого сценарію. Він буде містити ...
- слово "джерело", якщо сценарій використовується
- слово "main", якщо сценарій виконується І тест робиться з функції
- "" (null), якщо сценарій виконується І тест проводиться поза будь-якої функції, тобто ... на рівні самого сценарію.
Наведена вище функція працює лише тоді, коли викликається на рівні сценарію (що все, що мені потрібно). Не вдалося б викликати всередині іншої функції, оскільки номер елемента масиву був би неправильним. Щоб змусити його працювати де завгодно, потрібно знайти верхню частину стека та перевірити це значення, що є складнішим.
Якщо вам це потрібно, ви можете отримати номер елемента "верхньої частини стека" за допомогою ...
local _top_of_stack=$(( ${#FUNCNAME[@]} - 1 ))
${#FUNCNAME[@]}- кількість елементів у масиві. Як масив на основі нуля, ми віднімаємо 1, щоб отримати останній елемент #.
Ці три функції використовуються разом для створення сліду стека функцій, подібного до Python, і вони можуть дати вам краще уявлення про те, як все це працює ...
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, як ніби вони є одним тривимірним масивом.