Pisahkan ruang nama untuk fungsi dan variabel dalam shell POSIX

13

Dalam tanda hubung, fungsi dan variabel tampaknya hidup di ruang nama yang terpisah:

fn(){
    fn="hello world"
}
fn; echo "The value is $fn!" #prints: The value is hello world!
fn; echo "The value is $fn!" #prints: The value is hello world!
#the fn variable doesn't conflict with the fn function

Apakah ini fitur khusus dasbor atau jaminan POSIX?

PSkocik
sumber
2
Kode Anda sebenarnya tidak membuktikan bahwa fnfungsi tersebut berada dalam ruang nama yang terpisah; jika mengeksekusi sekali menghapus definisi, kita akan melihat perilaku yang sama persis. Anda harus menunjukkan bahwa fungsi masih didefinisikan, misalnya dengan type fnsesudahnya.
alexis

Jawaban:

13

Jaminan :

2.9.5 Perintah Definisi Fungsi

Fungsi adalah nama yang ditentukan pengguna yang digunakan sebagai perintah sederhana untuk memanggil perintah majemuk dengan parameter posisi baru. Suatu fungsi didefinisikan dengan "perintah definisi fungsi". [...]

Fungsi ini bernama fname; aplikasi harus memastikan bahwa itu adalah nama (lihat Nama XBD) dan itu bukan nama utilitas bawaan khusus. Implementasi dapat memungkinkan karakter lain dalam nama fungsi sebagai ekstensi. Implementasi harus memelihara ruang nama yang terpisah untuk fungsi dan variabel.

ilkkachu
sumber
Perhatikan juga yang unsetmemiliki -vdan -funtuk memilih antara tidak menyetel variabel atau fungsi dengan nama yang diberikan. bash(kebalikan dari kebanyakan shell lain) akan menghapus foo fungsi dengan unset foojika tidak ada foovariabel (!), perilaku yang diizinkan oleh POSIX. Itu sebabnya dalam skrip POSIX itu praktik yang baik untuk selalu menggunakan salah satu -vatau -f(dan tentu saja dalam bashskrip juga, tetapi perhatikan bahwa unsetmungkin tidak selalu menghapus variabel dalam bash, bashpelingkupan variabel memiliki beberapa masalah).
Stéphane Chazelas
Perhatikan bahwa dalam bash pra-shellshock, Anda akan mengalami masalah saat mengekspor variabel dan fungsi dengan nama yang diberikan, karena bash akan berakhir menggunakan nama variabel lingkungan yang sama untuk keduanya (meletakkannya dua kali di lingkungan, beberapa perintah dapat menghapus salah satunya)
Stéphane Chazelas
8

Variabel dan fungsi berada di ruang nama yang berbeda di dasbor dan ini juga ditentukan oleh POSIX :

Implementasi harus memelihara ruang nama yang terpisah untuk fungsi dan variabel.

Selain itu, secara default variabel memiliki cakupan global. Beberapa shell (mis. Bash, ksh dan zsh) menyediakan localkata kunci untuk mendeklarasikan variabel dalam suatu fungsi dengan cakupan lokal saja.

Jadi, ya, perilaku yang Anda lihat dijamin oleh POSIX.

POSIX belum distandarisasi local , namun :

Deskripsi fungsi dalam proposal awal didasarkan pada gagasan bahwa fungsi harus berperilaku seperti skrip shell miniatur; yaitu, kecuali untuk variabel berbagi , sebagian besar elemen dari lingkungan eksekusi harus berperilaku seolah-olah mereka adalah lingkungan eksekusi baru, [..]

[..] Variabel lokal dalam suatu fungsi dipertimbangkan dan dimasukkan dalam proposal awal lain (dikontrol oleh built-in khusus local), tetapi dihapus karena tidak sesuai dengan model sederhana yang dikembangkan untuk fungsi dan karena ada beberapa oposisi untuk menambahkan built-in khusus baru yang bukan bagian dari praktik sejarah. Implementasi harus mencadangkan pengidentifikasi local(dan juga typeset, seperti yang digunakan dalam KornShell) jika mekanisme variabel lokal ini diadopsi dalam versi standar yang akan datang.

(penekanan milikku)

maxschlepzig
sumber
abu (dari akhir 80-an) yang menjadi dasar dasbor juga memiliki local, salah satu antarmuka paling konsisten di luar sana (dibandingkan dengan yang rusak parah di bash misalnya), bash baru-baru ini (4.4) meminjam local -(untuk lingkup lokal untuk opsi) dari abu (menerapkan pelingkupan gaya abu untuk satu $-variabel saja). ksh dan yash tidak memiliki local(hanya varian pdksh yang dimiliki local), tetapi typesetsebaliknya (dalam ksh93 typesetmenyediakan lingkup lokal (statis) hanya dalam fungsi yang dideklarasikan menggunakan sintaks ksh).
Stéphane Chazelas