Meneruskan deklarasi fungsi dalam skrip Bash atau Shell?

96

Apakah ada hal seperti itu bashatau setidaknya sesuatu yang serupa (work-around) seperti deklarasi maju, yang dikenal di C / C ++, misalnya?

Atau ada yang demikian karena misalnya selalu dijalankan dalam satu kali jalan (baris demi baris)?

Jika tidak ada deklarasi penerusan, apa yang harus saya lakukan agar skrip saya lebih mudah dibaca. Agak panjang dan definisi fungsi ini di awal, dicampur dengan variabel global, membuat skrip saya terlihat jelek dan sulit dibaca / dipahami)? Saya meminta untuk mempelajari beberapa praktik terkenal / terbaik untuk kasus seperti itu.


Sebagai contoh:

# something like forward declaration
function func

# execution of the function
func

# definition of func
function func
{
    echo 123
}
Kiril Kirov
sumber

Jawaban:

191

Pertanyaan bagus. Saya menggunakan pola seperti ini untuk sebagian besar skrip saya:

#!/bin/bash

main() {
    foo
    bar
    baz
}

foo() {
}

bar() {
}

baz() {
}

main "$@"

Anda dapat membaca kode dari atas ke bawah, tetapi kode tersebut tidak benar-benar mulai dijalankan hingga baris terakhir. Dengan melewati "$@"to main () Anda dapat mengakses argumen baris perintah $1, $2, et al seperti yang biasa Anda lakukan.

John Kugelman
sumber
3
Hai, bagaimana Anda menyusun data yang harus dibagikan antara foo / bar / baz dalam contoh Anda? Biasanya saya hanya meletakkannya di bagian atas script. Apakah ini masih terjadi saat menggunakan fungsi? Atau lebih baik menempatkan data global di main, lalu meneruskannya ke foo / bar / baz sebagai argumen? Apa praktik terbaiknya?
bodacydo
4
Saya lebih suka argumen. Kecuali itu, saya akan mengatur variabel global dalam mainatau dalam fungsi setelahnya main(misalnya, setupatau parseArguments). Saya menghindari variabel global yang ditetapkan di atas main- kode tidak boleh keluar dari main.
John Kugelman
Ini tampaknya agak analog dengan apa yang if _ _ name _ _ == "_ _ main _ _": main()dilakukan dengan python
Sergiy Kolodyazhnyy
Ini juga luar biasa saat menggunakan alat seperti Bats untuk menguji skrip Anda, memecah semuanya menjadi beberapa fungsi membuat pengujian komponen individual jauh lebih mudah. Lihat juga entri blog
dragon788
31

Ketika skrip bash saya tumbuh terlalu banyak, saya menggunakan mekanisme include:

File allMyFunctions:

foo() {
}

bar() {
}

baz() {
}

File main:

#!/bin/bash

. allMyfunctions

foo
bar
baz
mouviciel
sumber
28
Secara pribadi, ketika skrip shell mulai tumbuh melewati satu file, saya cenderung beralih ke bahasa yang berbeda ;-)
Joachim Sauer
Bukankah lebih baik digunakan source allMyfunctions?
pydoge
4
@pydoge: sourcetidak sesuai dengan POSIX. bashdidefinisikan sourcesebagai alias untuk .: mereka secara fungsional setara.
mouviciel