グローバル&ローカル変数の割り当て

いくつかのオンラインチュートリアルを通じてシェルスクリプトを学習していて、次のスクリプトにたどり着きました。これは、グローバル変数とローカル変数の違いを宣言します。

#!/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 "の関数呼び出しが再度変更されました"?誰かが説明できますか?

回答

var1は関数でローカルとして宣言されています。したがって、関数の実行中に、var1という名前の 2つの変数があります。グローバル変数とローカル変数です。ただし、関数はローカルのもののみを「見る」ことができます(ローカルのものはグローバルなものを「シャドウ」します)。したがって、関数内では、var1に対して行うことはすべてローカル変数に対して行われます。グローバルなvar1にはまったく触れられていません。

回答

への1つの方法local var1="local 1"var1の現在の値を保存する効果があり、最後に復元される関数を"local 1"に設定します。このメンタルモデルを使用すると、すべての変数をグローバルと見なすことができ、変数は関数の最後に復元されます。

関数の内部と外部の両方でechoを呼び出すのではなく、 varを出力した別の関数を呼び出しました。

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の内部からbarを呼び出すと、fooによって確立されたv1の値が取得されます。

dynamic scopelexical scopeのウェブ検索が役立つ場合があります。

コメント

  • "関数の最後に復元されます"、これで私の心がはっきりします!ありがとう

回答

Bashでは、ローカル変数を明示的に呼び出す必要があります。そうしないと、グローバル変数として扱われます。 。関数の内部(スコープが適用される場所)でも。

そして、変数に最後に設定されたスコープはすべて、ローカルで、単語local、または省略によるグローバル-echoを介して呼び出されたときに返されるものになります。

つまり、たとえば、関数が呼び出された後、ローカルスコープはvar1に設定されるため、この変数への変更は関数の外部では保持されません。ただし、グローバルはvar2に設定されたままなので、この変数を変更すると

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です