fungsi panggilan dinyatakan di bawah ini

15

Apakah mungkin untuk memanggil fungsi yang dideklarasikan di bawah dalam bash?

Contoh

if [ "$input" = "yes" ]; then
    YES_FUNCTION
elif [ "$input" = "no" ]; then
    NO_FUNCTION
else
    exit 0;
fi

YES_FUNCTION()
{
  .....
  .....
}

NO_FUNCTION()
{
  .....
  .....
}
msp9011
sumber

Jawaban:

36

Seperti kata orang lain, Anda tidak bisa melakukan itu.

Tetapi jika Anda ingin mengatur kode menjadi satu file sehingga program utama berada di bagian atas file, dan fungsi-fungsi lain didefinisikan di bawah ini, Anda dapat melakukannya dengan memiliki mainfungsi terpisah .

Misalnya

#!/bin/sh

main() {
    if [ "$1" = yes ]; then
        do_task_this
    else
        do_task_that
    fi
}

do_task_this() {
    ...
} 
do_task_that() {
    ...
} 

main "$@"; exit

Ketika kita memanggil maindi akhir file, semua fungsi sudah ditentukan. Eksplisit lewat "$@"ke maindiperlukan untuk membuat argumen baris perintah dari script yang terlihat dalam fungsi.

Eksplisit exitpada baris yang sama dengan panggilan ke main tidak wajib, tetapi dapat digunakan untuk mencegah skrip yang sedang berjalan kacau jika file skrip dimodifikasi. Tanpa itu, shell akan mencoba untuk melanjutkan membaca perintah dari file skrip setelah mainkembali. (lihat Bagaimana membaca seluruh skrip shell sebelum menjalankannya? )

ilkkachu
sumber
@ikkachu pikir itu harus bekerja .. biarkan aku periksa.
msp9011
7
Dengan skrip Bash, saya sering menggunakan [[ ${BASH_SOURCE[0]} = "$0" ]] && Main "$@"untuk memanggil fungsi utama sehingga saya dapat sumbernya di skrip lain tanpa Maindieksekusi. Kemudian saya dapat menggunakan kembali fungsi atau menulis tes untuk memeriksanya.
BlackJack
11
Memiliki main "$@"; exit(dengan exitpada baris yang sama dengan main) juga berguna sebagai perlindungan terhadap file yang sedang dimodifikasi saat ditafsirkan.
Stéphane Chazelas
2
@ JoL, apa yang dibaca tidak dibaca lagi, dan shell perlu membaca dan mem-parsing seluruh teks dari sebuah loop sebelum mulai menjalankannya, tetapi kemudian setelah loop kembali itu akan melanjutkan membaca dari sisa file di posisi saat ini (dan jika file telah dimodifikasi itu akan mengacaukan segalanya). Jika semuanya dalam fungsi, shell perlu membaca semuanya sebelum mulai melakukan apa pun (kecuali mendefinisikan fungsi-fungsi itu), jika kita meletakkannya exitdi baris yang sama seperti mainkita memastikan shell tidak akan membaca apa pun lagi dari file setelah mainkembali.
Stéphane Chazelas
1
@MontyHarder, tidak masalah jika Anda menggunakan main; exit, main; exit $?atau main <EOF>, dalam semua kasus, kode keluar maindigunakan sebagai kode keluar dari skrip. Itu exithanya untuk mencegah hal-hal menjadi kacau jika seseorang mengedit skrip saat sedang berjalan.
ilkkachu
13

Tidak, fungsinya harus ada di lingkungan shell pada saat memanggilnya.

Google "Shell Style Guide" memiliki untuk memperbaiki ini:

Fungsi yang dipanggil maindiperlukan untuk skrip yang cukup lama untuk memuat setidaknya satu fungsi lainnya.

Di akhir skrip, setelah semua fungsi, sebagai satu-satunya pernyataan tidak dalam suatu fungsi, Anda akan miliki

main "$@"

Ini akan memanggil mainfungsi dengan parameter apa pun yang diberikan skrip. The mainFungsi bisa terletak di bagian atas script (panduan gaya mengatakan untuk meletakkannya di bagian bawah, tetapi sekali lagi, ia mengatakan banyak hal).

Ketika shell masuk ke mainpanggilan, semua fungsi dalam skrip telah diuraikan dan karena itu dapat dipanggil dari dalam mainfungsi.

Kusalananda
sumber
9

Tidak, fungsi harus dideklarasikan sebelum digunakan. Script Shell dibaca baris demi baris dan ditindaki baris demi baris; jadi fungsi tidak ada sampai deklarasi dijalankan.

Stephen Kitt
sumber
kamu benar. masalahnya adalah saya memiliki 30+ fungsi dalam sebuah skrip. cukup sulit ketika kita membaca kodenya. Di Cdalamnya nyaman.
msp9011
3
Anda dapat menempatkan deklarasi fungsi Anda di file lain dan sumbernya ( . yourfile).
Stephen Kitt
Ya, saya sudah mencobanya, tetapi syaratnya adalah memiliki satu skrip.
msp9011
@SivaPrasath Apa sebenarnya masalahnya? Cukup tentukan semua fungsi, bahkan mungkin menempatkan kode utama dalam suatu fungsi dan kemudian baris terakhir menunjukkan fungsi yang dipanggil dan berisi bagian utama dari skrip.
BlackJack
@SivaPrasath Di C, Anda tidak memiliki ifpernyataan kosong di luar fungsi. Fungsi tidak harus didefinisikan ketika Anda menyatakan itu iffungsi -mengandung, hanya ketika Anda menelepon itu.
chepner
4

Shell tidak memiliki konsep declaringfungsi. Jadi, Anda tidak dapat memiliki deklarasi maju.

Sebagai konsekuensinya, Anda harus memiliki implementasi fungsi dibaca oleh shell sebelum dapat dipanggil.

schily
sumber
4
Secara teknis, beberapa shell (ksh, zsh) memiliki fitur fungsi autoloading yang dapat dilihat sebagai beberapa bentuk deklarasi (di mana autoload fmendeklarasikan fungsi, tetapi tubuhnya hanya dimuat pada permintaan pertama). Itu tidak berlaku untuk OP bashsekalipun.
Stéphane Chazelas