GNU/Linux >> Belajar Linux >  >> Linux

Referensi Nama Edaran Dalam Fungsi Bash Shell, Tapi Tidak Di Ksh?

Saya sedang menulis serangkaian fungsi shell yang ingin saya gunakan di Bash dan KornShell93, tetapi dengan Bash saya mendapatkan peringatan "referensi nama melingkar".

Inilah inti masalahnya:

function set_it {
    typeset -n var="$1"

    var="hello:$var"
}

function call_it {
    typeset -n var="$1"

    set_it var
}

something="boff"
call_it something
echo "$something"

Menjalankannya:

$ ksh script.sh
hello:boff

$ bash script.sh
script.sh: line 4: warning: var: circular name reference
hello:

KornShell93 melakukan persis seperti yang saya inginkan, tetapi Bash gagal, dan juga memperingatkan tentang hal yang sama pada baris 2 jika something variabel dalam skrip bernama var sebagai gantinya.

Saya ingin memiliki var variabel menjadi lokal untuk setiap fungsi, itulah sebabnya saya menggunakan typeset , tetapi Bash tampaknya tidak suka "mengalihkan" namaref ke variabel dengan nama yang sama dengan namareferensi itu sendiri. Saya tidak dapat menggunakan local -n atau declare -n karena akan merusak ksh yang tidak memiliki ini, dan bahkan jika saya melakukannya, itu tidak menyelesaikan masalah.

Satu-satunya solusi yang saya temukan adalah menggunakan nama variabel unik di setiap fungsi , yang tampaknya agak konyol karena bersifat lokal.

Manual Bash mengatakan yang berikut tentang typeset :

typeset […]

-n Beri setiap nama nameref atribut, menjadikannya sebagai referensi nama
ke variabel lain. Variabel lain itu
didefinisikan oleh nilai name . Semua referensi dan
penugasan ke name , kecuali untuk mengubah -n
atribut itu sendiri, dilakukan pada variabel yang direferensikan oleh nilai nama.

[…]

Saat digunakan dalam suatu fungsi, declare dan typeset buat setiap nama
lokal, seperti pada local perintah, kecuali -g opsi
disediakan. Jika nama variabel diikuti oleh =value , nilai
variabel disetel ke value .

Jelas bahwa ada sesuatu yang saya tidak mengerti tentang referensi nama Bash dan variabel fungsi-lokal.

Jadi, pertanyaannya adalah:Dalam hal ini, apakah saya melewatkan sesuatu tentang penanganan Bash terhadap variabel referensi nama, atau apakah ini bug/salah fitur di Bash?

Perbarui :Saat ini saya bekerja dengan GNU bash, version 4.3.39(1)-release (x86_64-apple-darwin15) serta dengan GNU bash, version 4.3.46(1)-release (x86_64-unknown-openbsd6.0) . Bash yang dikirimkan dengan macOS terlalu tua untuk mengetahui tentang referensi nama sama sekali.

Perbarui :Lebih pendek lagi:

function bug {
    typeset -n var="$1"
    printf "%sn" "$var"
}

var="hello"
bug var

Menghasilkan bash: warning: var: circular name reference . var dalam fungsi harus memiliki cakupan yang berbeda dari var dalam lingkup global. Ini memberlakukan pembatasan yang tidak perlu pada penelepon. Pembatasannya adalah “Anda tidak boleh memberi nama variabel apa pun yang Anda inginkan, karena mungkin ada bentrokan nama dengan nameref (lokal) dalam fungsi ini”.

Terkait:Bagaimana cara beralih dari pengguna root ke pengguna lain yang memiliki shell nologin?

Jawaban yang Diterima:

Chet Ramey (pengelola Bash) mengatakan

Ada diskusi ekstensif tentang namerefs di bug-bash awal tahun ini
. Saya memiliki saran yang masuk akal tentang cara mengubah perilaku ini,
dan saya akan melihatnya setelah bash-4.4 dirilis.

Sementara itu, saya menggunakan sedikit mengaburkan nama variabel nameref lokal saya, sehingga mereka tidak berbenturan di dalam perpustakaan atau (semoga) dengan nama variabel shell global.

Di bash 5.0, ini sedikit diperbaiki (tetapi tidak benar-benar diperbaiki). Berikut adalah perilaku yang diamati:

$ foo () { typeset -n var="$1"; echo "$var"; }
$ var=hello
$ foo var
bash: typeset: warning: var: circular name reference
bash: warning: var: circular name reference
bash: warning: var: circular name reference
hello

Ini menunjukkan bahwa itu berhasil, tetapi ada juga beberapa peringatan.

Entri BERITA yang relevan mengatakan

i. A nameref name resolution loop in a function now resolves to a variable by
that name in the global scope.

Linux
  1. Menyesuaikan shell Bash

  2. Mengapa Dokumen Induk Shell Di Sini Tidak Berfungsi Untuk Sub-perintah Di Dash Tapi Bash Bekerja?

  3. Perintah Tidak Ditemukan Di Zsh, Tetapi Ditemukan Di Bash?

  1. Cara apa pun untuk keluar dari skrip bash, tetapi tidak keluar dari terminal

  2. Mengapa Bash ada di mana-mana (di sebagian besar jika tidak semua distribusi Linux)?

  3. `ssh <host>` adalah shell login, tetapi `ssh <host> <command>` bukan?

  1. Perbedaan Antara Variabel Shell Yang Diekspor Dan Yang Tidak Di Bash?

  2. Fungsi Dalam Variabel Shell?

  3. Modul Python tidak ditemukan di terminal tetapi di shell python, Linux