ฉันเพิ่งสร้างไลบรารีสคริปต์ชนิดเดียวกับที่ทำงานมากเช่น BusyBox ในนั้นฉันใช้ฟังก์ชั่นต่อไปนี้เพื่อทดสอบว่ามีการจัดหา ...
function isSourced () {
[[ "${FUNCNAME[1]}" == "source" ]] && return 0
return 1
}
อาร์เรย์ FUNCNAME ที่ได้รับการดูแลโดย Bash นั้นเป็นฟังก์ชันการเรียกฟังก์ชัน $FUNCNAME
(หรือ${FUNCNAME[0]}
) เป็นชื่อของฟังก์ชั่นการดำเนินการในปัจจุบัน ${FUNCNAME[1]}
เป็นชื่อของฟังก์ชั่นที่เรียกมันและอื่น ๆ
รายการสูงสุดเป็นค่าพิเศษสำหรับสคริปต์ มันจะมี ...
- คำว่า "แหล่งที่มา" ถ้าสคริปต์นั้นมีที่มา
- คำว่า "main" ถ้าสคริปต์ถูกเรียกใช้งานและการทดสอบกำลังทำจากภายในฟังก์ชัน
- "" (null) หากสคริปต์ถูกดำเนินการและการทดสอบกำลังดำเนินการนอกฟังก์ชั่นใด ๆ นั่นคือ ... ที่ระดับของสคริปต์เอง
ฟังก์ชั่นด้านบนใช้งานได้จริงเมื่อเรียกที่ระดับสคริปต์เท่านั้น (ซึ่งเป็นสิ่งที่ฉันต้องการ) มันจะล้มเหลวถ้าเรียกจากภายในฟังก์ชันอื่นเนื่องจากหมายเลขรายการอาร์เรย์จะผิด เพื่อให้ทำงานได้ทุกที่ต้องค้นหาด้านบนสุดของสแต็กและทดสอบค่าซึ่งมีความซับซ้อนมากขึ้น
หากคุณต้องการคุณจะได้รับหมายเลขรายการอาเรย์ของ "top of the stack" ด้วย ...
local _top_of_stack=$(( ${#FUNCNAME[@]} - 1 ))
${#FUNCNAME[@]}
คือจำนวนรายการในอาร์เรย์ ในฐานะที่เป็นอาร์เรย์แบบ zero-based เราลบ 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 ราวกับว่ามันเป็นหนึ่งในสามมิติ