none
変数及び関数のスコープについて RRS feed

  • 質問

  • 変数及び関数のスコープについて教えてください。

    【検証環境】

    ・PowerShellスクリプトで共通利用する関数をまとめた shared.ps1 というスクリプトファイルを作成

    ・呼び出し元(親スクリプトファイル)となるスクリプトファイル update.ps1 で shared.ps1 をドットソース形式でインクルードする

    ・shared.ps1 では update.ps1 でスコープを指定せずに定義した変数を含む文字列を利用して処理を行う


    検証した動作では、shared.ps1 内の関数から参照するupdate.ps1の変数は

    global,local,script,private のすべてのスコープを定義しても参照できました。

    これは、呼び出し元(親スクリプトファイル)となるスクリプトファイル update.ps1 で shared.ps1 をドットソース形式でインクルードした場合、

    shared.ps1 内からは呼び出し元(親スクリプトファイル)となるスクリプトファイル update.ps1 の変数は

    すべて参照可能という判断ができると思うのですが、そのような認識で問題ないでしょうか?

    それとも、たまたま参照できただけということになるのでしょうか?

    変数、関数のスコープはPowerShellの利用方法(コンソール、スクリプトファイル)で動作が異なるような情報を確認しています。

    これらの情報を整理できればと思いますので、ご回答よろしくお願いいたします。


    2017年3月31日 14:37

すべての返信

  • PowerShellの言語仕様書の3.5.5 Dot source notation節には、

    However, when dot source notation is used, no new scope is created before the command is executed, so additions/changes it would have made to its own local scope are made to the current scope instead.

    と書かれています。

    つまり、ドットソースを用いた場合は新たなスコープが作られず、呼び出し元のスコープ上で実行されます。そのため、呼び出されるスクリプト内のglobal,local,script,privateの各スコープラベルは、呼び出す側のスコープラベルと同一の内容を指すことになります。

    ドットソースというのは、スクリプトを呼び出す、というより、スクリプトに別のスクリプトを追記する…と捉えた方がイメージとしては近いかもしれません。

    よく使う関数をまとめて定義する場合、スクリプトファイル(.ps1)ではなくモジュール(.psm1)を利用するのが一般的かと思います。モジュール内に関数や変数を定義しておき、公開したい関数や変数のみ、Export-ModuleMemberコマンドで公開することができます。

    逆にモジュール内の関数ではscriptラベルを用いれば、当該モジュール内でのみ参照/書き換え可能な変数が定義できます。

    (ただし、モジュール内関数でglobalスコープを付けた変数を定義すると、呼び出す側のスクリプトで定義された変数を読み書き可能となる。また、スコープラベルを付けないときで、呼び出す側のスクリプトで同名の変数が定義されていた場合、値のコピーが行われる。)

    2017年3月31日 21:33
    モデレータ