Saya harus meneruskan fungsi sebagai parameter di Bash. Misalnya kode berikut ini:
function x() {
echo "Hello world"
}
function around() {
echo "before"
eval $1
echo "after"
}
around x
Haruskah mengeluarkan:
before
Hello world
after
Saya tahu eval
tidak benar dalam konteks itu tapi itu hanya sebuah contoh :)
Ada ide?
function
kata tersebut, Anda tidak dapat mengakses metode internal tersebut sampai Anda menjalankan metode tingkat atas.Saya tidak berpikir ada orang yang menjawab pertanyaan itu. Dia tidak bertanya apakah dia bisa menggemakan string secara berurutan. Sebaliknya, penulis pertanyaan ingin tahu apakah dia dapat mensimulasikan perilaku penunjuk fungsi.
Ada beberapa jawaban yang mirip dengan yang saya lakukan, dan saya ingin mengembangkannya dengan contoh lain.
Dari penulis:
function x() { echo "Hello world" } function around() { echo "before" ($1) <------ Only change echo "after" } around x
Untuk memperluas ini, kita akan memiliki fungsi x echo "Hello world: $ 1" untuk menunjukkan kapan eksekusi fungsi benar-benar terjadi. Kami akan mengirimkan string yang merupakan nama fungsi "x":
function x() { echo "Hello world:$1" } function around() { echo "before" ($1 HERE) <------ Only change echo "after" } around x
Untuk menggambarkan ini, string "x" dilewatkan ke fungsi around () yang menggemakan "sebelum", memanggil fungsi x (melalui variabel $ 1, parameter pertama diteruskan ke sekitar) meneruskan argumen "DI SINI", akhirnya bergema setelah .
Selain itu, ini adalah metodologi untuk menggunakan variabel sebagai nama fungsi. Variabel sebenarnya menahan string yang merupakan nama fungsi dan ($ variabel arg1 arg2 ...) memanggil fungsi yang meneruskan argumen. Lihat di bawah:
function x(){ echo $3 $1 $2 <== just rearrange the order of passed params } Z="x" # or just Z=x ($Z 10 20 30)
memberikan: 30 10 20, di mana kami menjalankan fungsi bernama "x" yang disimpan dalam variabel Z dan melewati parameter 10 20 dan 30.
Di atas di mana kita mereferensikan fungsi dengan menetapkan nama variabel ke fungsi sehingga kita dapat menggunakan variabel sebagai pengganti benar-benar mengetahui nama fungsi (yang mirip dengan apa yang mungkin Anda lakukan dalam situasi penunjuk fungsi yang sangat klasik di c untuk menggeneralisasi aliran program tetapi pra -memilih panggilan fungsi yang akan Anda buat berdasarkan argumen baris perintah).
Di bash ini bukan penunjuk fungsi, tetapi variabel yang merujuk ke nama fungsi yang nanti Anda gunakan.
sumber
()
bukankah itu memulai sub-shell?tidak perlu digunakan
eval
function x() { echo "Hello world" } function around() { echo "before" var=$($1) echo "after $var" } around x
sumber
Anda tidak dapat meneruskan apa pun ke fungsi selain string. Proses substitusi dapat memalsukannya. Bash cenderung menahan FIFO sampai perintahnya diperluas hingga selesai.
Ini yang konyol
foldl() { echo $(($(</dev/stdin)$2)) } < <(tr '\n' "$1" <$3) # Sum 20 random ints from 0-999 foldl + 0 <(while ((n=RANDOM%999,x++<20)); do echo $n; done)
Fungsi dapat diekspor, tetapi ini tidak semenarik yang pertama kali muncul. Saya merasa ini terutama berguna untuk membuat fungsi debugging dapat diakses oleh skrip atau program lain yang menjalankan skrip.
( id() { "$@" } export -f id exec bash -c 'echowrap() { echo "$1"; }; id echowrap hi' )
id
masih hanya mendapatkan string yang kebetulan menjadi nama fungsi (diimpor secara otomatis dari serialisasi di lingkungan) dan argumennya.Komentar Pumbaa80 untuk jawaban lain juga bagus (
eval $(declare -F "$1")
), tetapi berguna terutama untuk array, bukan fungsi, karena selalu global. Jika Anda menjalankan ini dalam suatu fungsi, yang akan dilakukannya hanyalah mendefinisikan ulang, jadi tidak ada efeknya. Ini tidak dapat digunakan untuk membuat penutupan atau fungsi parsial atau "contoh fungsi" bergantung pada apa pun yang terjadi untuk terikat dalam cakupan saat ini. Paling banter ini dapat digunakan untuk menyimpan definisi fungsi dalam string yang akan didefinisikan ulang di tempat lain - tetapi fungsi tersebut juga hanya dapat di-hardcode kecuali tentu sajaeval
digunakanPada dasarnya Bash tidak bisa digunakan seperti ini.
sumber
Pendekatan yang lebih baik adalah menggunakan variabel lokal dalam fungsi Anda. Masalahnya kemudian menjadi bagaimana Anda menyampaikan hasilnya kepada penelepon. Salah satu mekanismenya adalah dengan menggunakan substitusi perintah:
function myfunc() { local myresult='some value' echo "$myresult" } result=$(myfunc) # or result=`myfunc` echo $result
Di sini hasilnya adalah output ke stdout dan pemanggil menggunakan substitusi perintah untuk menangkap nilai dalam variabel. Variabel tersebut kemudian dapat digunakan sesuai kebutuhan.
sumber
Anda harus memiliki sesuatu di sepanjang baris:
function around() { echo 'before'; echo `$1`; echo 'after'; }
Anda kemudian dapat menelepon
around x
sumber
eval mungkin satu-satunya cara untuk mencapainya. Satu-satunya kelemahan nyata adalah aspek keamanannya, karena Anda perlu memastikan bahwa tidak ada yang berbahaya yang masuk dan hanya fungsi yang ingin Anda panggil yang akan dipanggil (bersama dengan memeriksa bahwa tidak ada karakter jahat seperti ';' di dalamnya juga).
Jadi jika Anda yang memanggil kode tersebut, maka kemungkinan besar eval adalah satu-satunya cara untuk melakukannya. Perhatikan bahwa ada bentuk eval lain yang kemungkinan akan berfungsi terlalu melibatkan subperintah ($ () dan ``), tetapi tidak lebih aman dan lebih mahal.
sumber
eval $1
akan memanggil fungsi menggunakanif declare -F "$1" >/dev/null; then eval $1; fi
eval $(declare -F "$1")