はじめに
最近職場で以下のようなコードを見かけたのですが、恥ずかしながら最初は意味が全く分かりませんでした。
コードを書いた本人に聞いてみたところ「スクリプトブロックという機能を利用している」とのことだったので、今回はスクリプトブロックについて調べた結果をまとめてみました。
test.ps1
function SayHello ($param) {
Invoke-Command $param
Write-Host "Hello, world!"
}
SayHello {
Write-Host "A"
Write-Host "B"
Write-Host "C"
}
test.ps1の実行結果
A
B
C
Hello, world!
学習環境
今回はWindows PowerShell ISEとVS Codeを使いました。
スクリプトブロックとは
- Microsoftのリファレンスを見ると、以下のように書かれていました。
PowerShell プログラミング言語では、スクリプト ブロックは、1 つのユニットとして使用できるステートメントまたは式のコレクションです。 ステートメントのコレクションは、中かっこ ({}) で囲んだり、関数として定義したり、スクリプト ファイルに保存したりできます。 スクリプト ブロックは値を返し、パラメーターと引数を受け取ることができます。
つまり、最小のスクリプトブロックは以下のように定義されることになると思います。
test2.ps1
{
Write-Host "test"
}
test2.ps1の実行結果
test
スクリプトブロックを変数に入れる
- スクリプトブロックという処理のまとまりを変数に入れることで、見かけはJavascriptの無名関数のような感じです。
- 普通の関数のように呼び出せないので、
Invoke-Command
か&
を使って実行します。
test3.ps1
$func = {
Write-Host "test"
}
Write-Host "Start test..."
& $func
test3.ps1の実行結果
Start test...
test
スクリプトブロックに変数を渡す
- さらに一歩進んで、「スクリプトブロックを変数に入れる」だけでなく「スクリプトブロックに変数を渡す」という処理を入れてみました。
-
$func
の定義部分は、引数ありの普通の関数みたいな感じです。
test4.ps1
$message = "Hello, world!"
$myName = "nkojima"
$func = { param($msg, $name)
Write-Host "${msg} from ${name}"
}
& $func -msg $message -name $myName
test4.ps1の実行結果
test
最初のコードについて
- ここまで理解すると、「はじめに」に書いたコードは、SayHello関数の引数として直接スクリプトブロックを渡していることが分かります。
- そのため、以下のように書き換えることが可能です。
test.ps1の修正版
function SayHello ($param) {
Invoke-Command $param
Write-Host "Hello, world!"
}
$func = {
Write-Host "A"
Write-Host "B"
Write-Host "C"
}
SayHello $func
test.ps1の修正版の実行結果
A
B
C
Hello, world!
まとめ
- 古典的なコードの書き方しか知らないと戸惑うと思いますが、少し書いている内に慣れてくると思います。
- スクリプトブロックを引数として使うと、例えば以下のようにメイン処理の前後に必ず入れたい処理を確実に入れることができるというような使い方ができると思います。
- 例えば前処理に「コネクションの作成」、後処理に「コネクションのクローズ」などを入れると、メインの処理を(スクリプトブロック内に)書くことに注力できるようになります。
- ただしこの使い方はパッと思いついたものなので、もしかすると不適切かもしれませんが...
test5.ps1
function SayHello ($param) {
Write-Host "ここで前処理を行う"
Invoke-Command $param
Write-Host "ここで後処理を行う"
}
SayHello {
Write-Host "メインの処理を行う"
}
Write-Host "処理終了"
test5.ps1
ここで前処理を行う
メインの処理を行う
ここで後処理を行う
処理終了