Cara menentukan nama fungsi dari dalam suatu fungsi

163

Jika saya memiliki skrip Bash seperti:

#!/bin/bash

f() {
  # echo function name, "f" in this case
}

Apakah ada cara untuk melakukan ini? Ini dapat digunakan dalam pesan bantuan seperti

printf "Usage: %s: blah blah blah \n" $(basename $0) >&2; 

Hanya dalam hal ini yang saya inginkan bukan $0, yang merupakan nama file dari skrip.

Yan
sumber
2
Terkait: Bash logging framework yang menggunakan FUNCNAMEarray dan variabel Bash lainnya: github.com/codeforester/base/blob/master/lib/stdlib.sh . Lihat fungsi log_debug_enterdan log_debug_leavekhususnya.
codeforester

Jawaban:

236

Anda dapat menggunakan ${FUNCNAME[0]}di bashuntuk mendapatkan nama fungsi.

TheBonsai
sumber
79

Dari Manual Referensi Bash :

FUNCNAME

Variabel array yang berisi nama-nama semua fungsi shell saat ini dalam tumpukan panggilan eksekusi. Elemen dengan indeks 0 adalah nama dari setiap fungsi shell yang sedang dijalankan. Elemen terbawah (yang memiliki indeks tertinggi) adalah "utama". Variabel ini hanya ada ketika fungsi shell mengeksekusi. Tugas untuk FUNCNAME tidak berpengaruh dan mengembalikan status kesalahan. Jika FUNCNAME tidak disetel, FUNCNAME akan kehilangan properti khususnya, bahkan jika kemudian disetel ulang.

Variabel ini dapat digunakan dengan BASH_LINENO dan BASH_SOURCE. Setiap elemen FUNCNAME memiliki elemen yang sesuai di BASH_LINENO dan BASH_SOURCE untuk menggambarkan tumpukan panggilan. Misalnya, $ {FUNCNAME [$ i]} dipanggil dari file $ {BASH_SOURCE [$ i + 1]} di nomor baris $ {BASH_LINENO [$ i]}. Penelepon bawaan menampilkan tumpukan panggilan saat ini menggunakan informasi ini.

Ketika bash array diakses tanpa indeks, elemen pertama dari array akan dikembalikan, sehingga $FUNCNAMEakan bekerja dalam kasus-kasus sederhana untuk memberikan nama fungsi segera saat ini, tetapi juga mengandung semua fungsi lain di tumpukan panggilan. Sebagai contoh:

# in a file "foobar"
function foo {
    echo foo
    echo "In function $FUNCNAME: FUNCNAME=${FUNCNAME[*]}" >&2
}

function foobar {
    echo "$(foo)bar"
    echo "In function $FUNCNAME: FUNCNAME=${FUNCNAME[*]}" >&2
}

foobar

Akan menghasilkan:

$ bash foobar
In function foo: FUNCNAME=foo foobar main
foobar
In function foobar: FUNCNAME=foobar main
bschlueter
sumber
6
Saya masih belum mengerti. Mengapa menambahkan [0]jika itu tersirat dengan mengakses variabel yang tidak didekorasi?
Tom Hale
15
Karena itu menipu dan tidak mengetahui tipe aktual variabel? Tentu, itu tidak selalu diperlukan, tetapi seperti banyak bash-isme lainnya, ini adalah konvensi yang malas. Lebih baik bersikap eksplisit daripada mendua.
bschlueter
36

Saya gunakan ${FUNCNAME[0]}untuk mencetak nama fungsi saat ini

Verdigrass
sumber
@ bschlueter tetapi ketika Anda mereferensikan sebuah array tanpa memperlakukannya seperti sebuah array di Bash, ia hanya mencetak nilai pertama; oleh karena itu, bagaimana jawaban yang diterima salah?
Alexej Magura
4
Tentu, dan itu nyaman, tetapi mengerikan untuk perawatan dan pengujian. Jangan malas, jelaskan.
bschlueter
1

Contoh lain:

# in a file "foobar"
foo() {
    echo "$FUNCNAME fuction begins"
}

foobar() {
    echo "$FUNCNAME fuction begins"
}

echo 'begin main'
foo
foobar
echo 'end main'

Akan menghasilkan:

begin main
foo fuction begins
foobar fuction begins
end main
Mickey White
sumber
-1

Cara paling sederhana untuk mendapatkan nama fungsi (dari dalam suatu fungsi)

echo $0
jasonleonhard
sumber
Tolong berhenti menyalahgunakan ###jawaban Anda.
Marcin Orlowski
@MarcinOrlowski Apakah Anda baik-baik saja? Sepertinya Anda bisa menggunakan pelukan.
jasonleonhard