自作関数やスクリプトの出力にヘッダーを表示させる(カスタムオブジェクトの出力)
構文
$result=New-Object PSObject
$result | Add-Member NoteProperty HeaderName1 abc
$result | Add-Member NoteProperty HeaderName2 123
$result
解説
PowerShellの多くのコマンドレットでは、出力結果にヘッダーが付与されます。たとえば、Get-ChildItemコマンドレットでは以下のように、現在位置のパスや、Mode、LastWriteTime、Length、Nameの各ヘッダー、さらにヘッダーと内容の区切り記号が表示されます。
PS U:\Ps> Get-ChildItem
ディレクトリ: U:\Ps
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2010/09/08 6:52 Folder1
(以下略)
自作の関数やスクリプトでも、ファイルやフォルダーを出力するのであればこのようなヘッダーがつきます。しかし、加工したデータを出力したい場合、ファイルやフォルダーばかりを出力するわけにはいきません。
たとえば次の例では、入力した整数の2進、10進、16進文字列を出力します。
PS U:\Ps> `
>> function ConvertBase10ToString([int]$x)
>> {
>> "{1}:{0}:{0:X}" -f $x,[Convert]::ToString($x,2)
>> }
>>
PS U:\Ps> 252..255 | %{ ConvertBase10ToString $_ }
11111100:252:FC
11111101:253:FD
11111110:254:FE
11111111:255:FF
PS U:\Ps>
2進と10進と16進という3種類のデータを出力しているので、Base2、Base10、Base16などと3つの列に分けて出力してほしいところです。それを実現するには、関数内でカスタムオブジェクトを出力します。
PS U:\Ps> `
>> function ConvertBase10([int]$x)
>> {
>> $result = New-Object PSObject
>> $result | Add-Member NoteProperty Base2 ([Convert]::ToString($x,2))
>> $result | Add-Member NoteProperty Base10 $x
>> $result | Add-Member NoteProperty Base16 ("{0:X}" -f $x)
>> $result
>> }
>>
PS U:\Ps> 252..255 | %{ ConvertBase10 $_ } | Format-Table -AutoSize
Base2 Base10 Base16
----- ------ ------
11111100 252 FC
11111101 253 FD
11111110 254 FE
11111111 255 FF
PS U:\Ps>
出力結果にヘッダーが付与されるようになりました。ただし、そのままではBase2とBase10の間が開きすぎるので、Format-Tableコマンドレットを使用しました。
補足
カスタムオブジェクトを出力する場合、特定の列(正確にはプロパティ)を取得するにはそのプロパティ名を指定します。
PS U:\Ps> 252..255 | %{ ConvertBase10 $_ } | %{ $_.Base16 }
FC
FD
FE
FF
PS U:\Ps>
これに対し、文字列を出力したConvertBase10ToStringの場合、次のようにします。
PS U:\Ps> 252..255 | %{ ConvertBase10ToString $_ } | %{ $_.Split(":")[2] }
「16進を取得する」という行為と「$_.Split(":")[2]」と記述することにはおよそ関連性がなく、後からスクリプトを読んだときに意味が非常に分かりにくくなります。他のコマンドライン環境ではこのような問題を今でも抱えています。文字列だけでなくオブジェクトを扱えるPowerShellがいかに使いやすいか分かります。