私はいくつかのオンラインチュートリアルを通してシェルスクリプトを学んでおり、グローバル変数とローカル変数の違いを宣言する次のスクリプトを得ました。
#!/bin/bash
# Experimenting with variable scope
var_change () {
local var1='local 1'
echo Inside function: var1 is $var1 : var2 is $var2
var1='changed again'
var2='changed again'
}
var1='global 1'
var2='global 2'
echo Before function call: var1 is $var1 : var2 is $var2
var_change
echo After function call: var1 is $var1 : var2 is $var2
出力は次のとおりです
関数呼び出し前:var1はグローバル1:var2はグローバル2
内部機能: var1ローカル1:var2はグローバル2
関数呼び出し後:var1はグローバル1:var2は再変更
私の質問...
var1
関数呼び出し後に「再変更」の代わりに「グローバル1」があるのはなぜですか?誰かがこれを説明できますか?
答え1
var1
関数内でローカルに宣言されました。したがって、関数の実行中に次のようなものがあります。二つ変数名var1
:グローバル変数とローカル変数。ただし、関数はローカル関数のみを「見る」ことができます(ローカル関数はグローバル関数を「隠します」)。したがって、関数内で実行するすべての操作はローカルvar1
変数に対して実行され、グローバル変数はvar1
まったく触れません。
答え2
これについて考える1つの方法は、現在の値を保存し、関数の終わりにそれを復元してから設定することを約束するlocal var1="local 1"
効果を想像することです。この精神モデルを使用すると、すべての変数をグローバル変数として処理し、関数の末尾から変数を復元できます。var1
"local 1"
var
この例は、関数の内側と外側の両方でechoを呼び出すのではなく、別の出力関数を呼び出す方が良いでしょう。
bash$ show(){ printf " The value of %s in %s is '%s'\n" $1 $2 ${!1} ; }
bash$ bar(){ show v1 bar_$1 ; }
bash$ foo(){ show v1 before_foo ; local v1 ; show v1 after_local ; \
v1="changed"; show v1 after_change ; bar via_foo ; }
bash$ v1="global"
bash$ show v1 global_scope
The value of v1 in global_scope is 'global'
bash$ foo
The value of v1 in before_foo is 'global'
The value of v1 in after_local is ''
The value of v1 in after_change is 'changed'
The value of v1 in bar_via_foo is 'changed'
bash$ bar direct
The value of v1 in bar_direct is 'global'
bash$ show v1 global_scope
The value of v1 in global_scope is 'global'
ここで、fooによって設定されたv1の値は、foo内のbar呼び出しから得られることがわかります。
Web検索がdynamic scope
役に立つlexical scope
かもしれません。
答え3
Bashはローカル変数を明示的に呼び出す必要があり、そうでない場合はグローバル変数として扱われます。範囲が適用される関数の内部でも可能です。
そして、変数に最終的に設定された範囲(ローカル、単語の明示的な宣言によるローカル、またはlocal
省略によるグローバル)は、viaが呼び出されたときに返されますecho
。
したがって、あなたの例では、関数が呼び出された後にローカルスコープがに設定され、var1
この変数に対するすべての変更は関数の外に残りません。ただし、グローバルはに設定されているため、var2
この変数は変更されます。