tech.guitarrapc.cóm

Technical updates

PowerShellのスプラッティングを試す

前々回の記事で、パイプラインを介してFunctionに渡す例をやりました。

PowerShellでHashTableや配列の値をパイプラインでFunctionに渡す

この時試したのは以下の方法です。

  • ハッシュテーブル(HashTable)
  • 配列(Array)
  • ハッシュテーブルを[PSCustomObject]でキャスト

さて、Functionへのパラメータ指定の方法として、ValueFromPipelineByPropertyNameの有用性を考えると、事前にパラメータを定義できたら。

スプラッティングとは

ここに詳細があります。

ようは、パラメータをバンドル(あらかじめまとめてしまう)という事です。

コマンドへ渡す前にパラメーターをバンドルできれば時間を節約できます。

Windows PowerShellでは、パラメーターをバンドルしてコマンドに渡す方法のことを "スプラッティング" と言います。

具体的にはどうする?

HashTableを作って、代入した変数をFunctionで利用する際に@で指定すればいいだけです。

例えば以下のHashTableでスプラッティングするなら……

$test =@{
    path="C:\hoge\fuga";
    sortby="Extention";
    count=1}

Functionへの指定時に$test.プロパティではなく@testとするだけという。

Test-Function @test

特にFunctionには制限がありません。

スプラッティングしてみよう

では早速テストしてみましょう。

前回の追記でサンプルとしてだしたFunctionを利用します。

function Get-FirstItem {

    [CmdletBinding()]
    param(
    [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
    [string]$path,
    [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
    [string]$sortby,
    [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
    [int]$count
    )

    begin{
    }

    process{

        Get-ChildItem $path | Sort-Object $sortby | Select-Object -First $count

    }

    end{
    }

}

パラメータをHashTableで定義します。

$test =@{
    path="C:\hoge\fuga";
    sortby="Extention";
    count=1}

スプラッティングして、Functionに渡します。

Get-FirstItem @test

おー、取得できました。

    ディレクトリ: C:\hoge\fuga


Mode         LastWriteTime Length Name
----         ------------- ------ ----
-a--- 2013/02/19     20:06     16 6.txt

受け手のパラメータを有効にしないと?

では、受け手のFunctionで、パラメータの[Parameter(ValueFromPipeline=$true)][Parameter(ValueFromPipelineByPropertyName=$true)]をそれぞれ有効/無効にするとどうなるか見てみましょう。

まずは、ValueFromPipeline=$trueだけを有効にしてみます。

function Get-FirstItem {

    [CmdletBinding()]
    param(
      [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
      [string]$path,
      [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
      [string]$sortby,
      [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
      [int]$count
    )

    process{
        Get-ChildItem $path | Sort-Object $sortby | Select-Object -First $count
    }
}

実行します。

Get-FirstItem @test

問題ないですね。

    ディレクトリ: C:\hoge\fuga


Mode         LastWriteTime Length Name
----         ------------- ------ ----
-a--- 2013/02/19     20:06     16 6.txt

では、両方無効にしてみます。

function Get-FirstItem {

    [CmdletBinding()]
    param(
      [Parameter(Mandatory=$true)]
      [string]$path,
      [Parameter(Mandatory=$true)]
      [string]$sortby,
      [Parameter(Mandatory=$true)]
      [int]$count
    )

    process{
        Get-ChildItem $path | Sort-Object $sortby | Select-Object -First $count
    }
}

実行してみます。

Get-FirstItem @test

問題なく実行できます。 (前回の検証では変数に変な値が入っていました)

    ディレクトリ: C:\hoge\fuga

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2013/02/19     20:06         16 6.txt

まとめ

プロパティをまとめる……ありはありですね。

HshTableのままで扱いたいけど、プロパティ指定にも使う場合は、スプラッティングかK,V指定で渡す。

PSCustomObjectへキャストするのに、一時的にHashTableを利用したならPSCustomObejctの方が楽なきもします。

いずれにしても、K,V指定が便利な場面と、プロパティ指定が楽な場面、それぞれに応じればいいのではないでしょうか。

Functionへのパラメータ指定

前回の記事のPSCustomObjectも含めて考えると、今後作成するFunctionは、ValueFromPipelineByPropertyNameValueFromPipelineの両方が$trueでもいい気もしますが。

牟田口先生のまとめ

勉強になるので、軽くまとめておきます。