スクリプトブロックと変数のスコープ
以下のコマンドの結果をみて、「ローカル変数はスクリプトブロック内でもアクセス可能なんだな」と認識していたのですが、
PS C:\> function call( $proc ) { &$proc } PS C:\> $a = 100 PS C:\> call { echo $a } 100
$aに値を代入すると、期待と異なる結果に。
PS C:\> function call( $proc ) { &$proc } PS C:\> $a = 100 PS C:\> call { echo $a; $a = 10; echo $a } 100 10 PS C:\> echo $a 100
ブロック内で代入したのに、外の値が更新されていない!ブロック内の出力を見る限りでは$aの参照と代入は正しくできているようなのだけど。ということで調べてみたら、CodeZine - Windows PowerShell 入門(8)−関数編3がヒット。こちらは関数内でのスコープの話なのだけど恐らく↑もおなじで、「スクリプトブロックの外の$a」と「スクリプトブロック内の$a」が別の変数となっているのが原因みたいです。まとめると、
- スクリプトブロックの外側で宣言した変数が、スクリプトブロックに封入される訳ではない。
- ↑の例でブロック内で$aが参照できるのは、$aが「ローカル変数」になっていて、配下のスコープからも参照できるから。
- $aをprivateにすると、ブロック内からは参照できなくなる。
PS C:\> $private:a = 100 PS C:\> call { echo $private:a; $private:a = 10; echo $private:a } 10 PS C:\> echo $private:a 100
- 参照はできるけど、ブロック内で「$a=10」とかすると、新たに変数が作成される。★ここがはまりポイント。
- で、ブロックの中で外の$aを更新したい場合は、$aのスコープが「スクリプト」であることを明示すればよい。
PS C:\> $a = 100 PS C:\> call { echo $script:a; $script:a = 10; echo $script:a } 100 10 PS C:\> echo $a 10
なかなか、趣深いな > Power Shell。