Bir işlevin içinden işlev adını belirleme


163

Ben gibi bir Bash betiği varsa:

#!/bin/bash

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

Bunu yapmanın bir yolu var mı? Bu, aşağıdakiler gibi yardım iletilerinde kullanılabilir:

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

Sadece bu durumda istediğim $0komut dosyasının dosya adı değil .


2
İlgili: FUNCNAMEDizi ve diğer Bash değişkenlerini kullanan Bash günlük kaydı çerçevesi : github.com/codeforester/base/blob/master/lib/stdlib.sh . Fonksiyonlarını bakın log_debug_enterve log_debug_leaveözellikle de.
codeforester

Yanıtlar:


236

Sen kullanabilirsiniz ${FUNCNAME[0]}içinde bashişlev adını almak için.


80

Gönderen Bash Reference Manual :

FUNCNAME

Yürütme çağrısı yığınında bulunan tüm kabuk işlevlerinin adlarını içeren bir dizi değişkeni. 0 dizinine sahip öğe, şu anda yürütülen kabuk işlevlerinin adıdır. En alttaki eleman (en yüksek endekse sahip olan eleman) "ana" dır. Bu değişken yalnızca bir kabuk işlevi yürütüldüğünde mevcuttur. FUNCNAME öğesine yapılan atamaların hiçbir etkisi yoktur ve hata durumu döndürür. FUNCNAME ayarlanmamışsa, daha sonra sıfırlansa bile özel özelliklerini kaybeder.

Bu değişken BASH_LINENO ve BASH_SOURCE ile kullanılabilir. FUNCNAME öğesinin her öğesinde, çağrı yığınını açıklamak için BASH_LINENO ve BASH_SOURCE öğelerinde karşılık gelen öğeler bulunur. Örneğin, $ {BAM_LINENO [$ i]} satır numarasındaki $ {BASH_SOURCE [$ i + 1]} dosyasından $ {FUNCNAME [$ i]} çağrıldı. Arayan yerleşik, bu bilgiyi kullanarak geçerli çağrı yığınını görüntüler.

Dizin olmadan bash dizilerine erişildiğinde, dizinin ilk öğesi döndürülür, bu nedenle $FUNCNAMEhemen geçerli işlevin adını sağlamak için basit durumlarda çalışır, ancak çağrı yığınındaki diğer tüm işlevleri de içerir. Örneğin:

# 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

Çıktı olacak:

$ bash foobar
In function foo: FUNCNAME=foo foobar main
foobar
In function foobar: FUNCNAME=foobar main

6
Hala anlamıyorum. [0]Dekode edilmemiş değişkene erişerek ima edildiyse neden eklemelisiniz ?
Tom Hale

15
Değişkenin gerçek türü hakkında aldatıcı ve cahil olduğu için mi? Elbette, her zaman gerekli değildir, ancak diğer birçok bash-izm gibi, tembel bir kongre. Belirsiz olmaktansa açık olmak daha iyidir.
bschlueter

36

${FUNCNAME[0]}Geçerli işlev adını yazdırmak için kullanıyorum


@bschlueter ancak bir diziye Bash'deki bir dizi gibi davranmadan başvurduğunuzda, yalnızca ilk değeri yazdırır; bu nedenle, kabul edilen cevap nasıl yanlıştır?
Alexej Magura

4
Elbette, bu kullanışlı, ancak bakım ve test için korkunç. Tembel olma, açık ol.
bschlueter

1

Başka bir örnek:

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

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

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

Çıktı olacak:

begin main
foo fuction begins
foobar fuction begins
end main

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.