Setelah membaca 24.2. Variabel Lokal , saya berpikir bahwa mendeklarasikan variabel var
dengan kata kunci local
berarti bahwa var
nilai hanya dapat diakses dalam blok kode yang dibatasi oleh kurung kurawal suatu fungsi.
Namun, setelah menjalankan contoh berikut, saya menemukan bahwa var
juga dapat diakses, dibaca dan ditulis dari fungsi dipanggil oleh blok kode - yaitu meskipun var
dinyatakan local
untuk outerFunc
, innerFunc
masih bisa membacanya dan mengubah nilainya.
#!/usr/bin/env bash
function innerFunc() {
var='new value'
echo "innerFunc: [var:${var}]"
}
function outerFunc() {
local var='initial value'
echo "outerFunc: before innerFunc: [var:${var}]"
innerFunc
echo "outerFunc: after innerFunc: [var:${var}]"
}
echo "global: before outerFunc: [var:${var}]"
outerFunc
echo "global: after outerFunc: [var:${var}]"
Keluaran:
global: before outerFunc: [var:] # as expected, `var` is not accessible outside of `outerFunc`
outerFunc: before innerFunc: [var:initial value]
innerFunc: [var:new value] # `innerFunc` has access to `var` ??
outerFunc: after innerFunc: [var:new value] # the modification of `var` by `innerFunc` is visible to `outerFunc` ??
global: after outerFunc: [var:]
T: Apakah itu bug di shell saya (bash 4.3.42, Ubuntu 16.04, 64bit) atau apakah itu perilaku yang diharapkan?
EDIT: Dipecahkan. Seperti dicatat oleh @MarkPlotnick, ini memang perilaku yang diharapkan.
var
kosong?var
diatur secara globalinnerFunc
, jadi mengapa tidak tetap sampai akhir skrip?Jawaban:
Variabel Shell memiliki cakupan dinamis . Jika variabel dideklarasikan sebagai lokal ke suatu fungsi, cakupan itu tetap sampai fungsi kembali.
Ada dua pengecualian:
di ksh93, jika suatu fungsi didefinisikan dengan
function_name () { … }
sintaks standar , maka variabel lokalnya mematuhi pelingkupan dinamis. Tetapi jika suatu fungsi didefinisikan dengan sintaks kshfunction function_name { … }
maka variabel lokalnya mematuhi scoping lexical / static, sehingga mereka tidak terlihat dalam fungsi lain yang disebut oleh ini.itu
zsh/private
Plugin autoloadable dizsh
menyediakan denganprivate
kata kunci / builtin yang dapat digunakan untuk mendeklarasikan variabel dengan lingkup statis.abu, bash, pdksh, dan turunannya, namun hanya memiliki pelingkupan dinamis.
sumber
local
?typeset
ataudeclare
ataulocal
deklarasi, cakupannya sampai fungsi kembali. Tanpa pernyataan seperti itu, ruang lingkupnya bersifat global.Ini bukan bug, panggilan di dalam konteks outerFunc menggunakan salinan lokal $ var. "Lokal" di outerFunc berarti global tidak berubah. Jika Anda memanggil innerFunc di luar outerFunc, maka akan ada perubahan ke $ var global, tetapi bukan $ var lokal outerFunc. Jika Anda menambahkan "lokal" ke innerFunc, maka $ var outerFunc tidak akan berubah - pada dasarnya, akan ada 3 di antaranya:
untuk menggunakan format namespace Perl, semacam.
sumber
Anda dapat menggunakan fungsi untuk memaksa lingkup lokal:
Contoh:
Hasil:
Sumber
sumber
Di
function innerFunc()
dalamvar='new value'
tidak dinyatakan sebagai lokal , oleh karena itu tersedia dalam lingkup terlihat (sekali fungsi telah dipanggil).Sebaliknya, di
function outerFunc()
dalamlocal var='initial value'
dinyatakan sebagai lokal , oleh karena itu tidak tersedia di lingkup global (bahkan jika fungsi telah dipanggil).Karena
innerFunc()
dipanggil sebagai anak kecilouterFunc()
, var berada dalam lingkup lokalouterFunc()
.man 1 bash
dapat membantu memperjelasPerilaku tersirat yang diharapkan dalam deskripsi dapat dicapai dengan menyatakan
local var='new value
difunction innerFunc()
.Seperti yang dinyatakan orang lain, ini bukan bug di shell bash. Semuanya berfungsi sebagaimana mestinya.
sumber
var
dalam lingkup global, setelah meneleponinnerFunc
melaluioutFunc
, tidak mencetaknew value
.