understanding-powershell-scriptblocks

PowerShell スクリプトブロックの説明

PowerShell スクリプトブロックの説明

このブログではスクリプトブロックについて説明します。PowerShell のいろいろなところでよく見られる中括弧{}で囲まれたものをスクリプトブロックと呼びます。

スクリプトブロックは、PowerShellの重要でユニークな構成単位です。スクリプトブロックは、基本的に、受け渡し可能で自由に実行できるポータブルなコードのブロックです。

PowerShell のスクリプトブロックはエクスプレッションです。エクスプレッションは、PowerShell がどのように実行するかを知っているコードです。たとえば、PowerShell には Invoke-Expression コマンドレットがあります。このコマンドレットは、基本的に文字列のような「非エクスプレッション」をエクスプレッションに「変換」します。文字列 write-output 'foo' は、何かできそうに見えてもそのままでは何もしませんが、Invoke-Expression に渡されると、PowerShell は期待通りにコードを実行します。

PS> Invoke-Expression -Command "write-output 'foo'"
foo

このブログはエクスプレッションの説明ではないので、スクリプトブロックの話に戻りましょう。スクリプトブロックの作成は、コードを中括弧 {} で囲むだけで簡単です。

PS> $myscriptblock = { 1 + 1 }
PS> $myscriptblock.GetType().FullName
System.Management.Automation.ScriptBlock

コードをスクリプトブロックに入れたら、いくつかの方法で実行できます。代表的なものは、呼び出し演算子(&)を使う方法と、Invoke-Command コマンドレットを使用する方法です。

PS> & $myscriptblock
2
PS> Invoke-Command -ScriptBlock $myscriptblock
2
PS>

スクリプトブロックは関数にも似ています。実際に、匿名関数と呼ばれることもあります。関数と同様に param ブロックを作成し、各パラメータの値を positional パラメータとして渡すことができます。

ArgumentList パラメータを使用して、スクリプトブロックにパラメータの引数を渡すこともできます。

PS> $myscriptblock = { param($Number) 1 + $Number }
PS> & $myscriptblock 3
3
PS> Invoke-Command -ScriptBlock $myscriptblock -ArgumentList 3
3

以上がスクリプトブロックを作成して実行する方法ですが、次に変数が内部でどのように動作するかを見てみましょう。残念ながら、変数の使い方は思ったほど直感的ではありません。

変数は、通常は、スクリプトブロック内で展開されます。

PS> $variable = 'foo'
PS> $myscriptblock = { "$variable bar" }
PS> & $myscriptblock

しかし、関数で使う変数のスコープ状況によって、これが期待通りに動作しない場合があります。下に示すように、変数を文字列に展開し、そのエクスプレッションをスクリプトブロックに変換する必要が生ずることがあります。ここでは、スクリプトブロック・クラスの Create() メソッドを呼び出して、$variable bar という文字列からスクリプトブロックを作成します。

$myscriptblock = [scriptblock]::Create("$variable bar")

変数とスクリプトブロックに関して注意が必要なもう1つの点は変数のスコープです。たとえば、スクリプトブロックの外で変数の値を設定した場合、内部でその変数を持つスクリプトブロックを作成すると、同じものとして参照されます。変数の値がスクリプトブロックの外で変更された場合、変数はスクリプトブロック内でも変更されます。

PS> $i = 2
PS> $scriptblock = { "Value of i is $i" }
PS> $i = 3
PS> & $scriptblock
Value of i is 3

変数の値がスクリプトブロック内だけで有効なようにしたい場合は、スクリプトブロックで GetNewClosure() メソッドを実行して、PowerShell でスクリプトブロックのコピーを作成するよう指定する必要があります。これで新しいコピーが作成され、変数の値が内部でのみ有効になります。

PS> $i = 2
PS> $scriptblock = { "Value of i is $i" }.GetNewClosure()
PS> $i = 3
PS> & $scriptblock
Value of i is 2

以上で、このブログでのスクリプトブロックの説明は終わりです。PowerShell スクリプトをより効率的に作成するのに、スクリプトブロックを利用してみてください。

 

関連ブログ


Comments
Comments are disabled in preview mode.
Thanks for subscribing! Loading animation