PowerShell 7 覚書き

PowerShell 7の覚書きです。

# PSCustomObjectからキーと名前を取得する。

`PSCustomObject`は非表示のプロパティ`PSObject`（`PSObject`型）を持ちます。これの`Properties`プロパティを使用して`PSCustomObject`のキーと名前（`Name`と`Value`）の配列を取得できます。

```powershell
$obj = [PSCustomObject]@{a=0; b=1; c=2}
$obj = ($obj.PSObject.Properties | Select-Object -Property Name, Value)
$obj.GetType()
# IsPublic IsSerial Name                                     BaseType
# -------- -------- ----                                     --------
# True     True     Object[]                                 System.Array
$obj | Format-Table
# Name Value
# ---- -----
# a        0
# b        1
# c        2
```

## 補足

`PSCustomObject`クラスの`PSObject`プロパティと`PSObject.Properties`は次の形式です。

```powershell
$props = [PSCustomObject]@{a=0; b=1; c=2}

$props.PSObject
# BaseObject          :
# Members             : {int a=0, int b=1, int c=2, ToString…}
# Properties          : {int a=0, int b=1, int c=2}
# Methods             : {ToString, GetType, Equals, GetHashCode}
# ImmediateBaseObject :
# TypeNames           : {System.Management.Automation.PSCustomObject, System.Object}

$props.PSObject.Properties
# Value           : 0
# MemberType      : NoteProperty
# IsSettable      : True
# IsGettable      : True
# TypeNameOfValue : System.Int32
# Name            : a
# IsInstance      : True
# 
# Value           : 1
# MemberType      : NoteProperty
# IsSettable      : True
# IsGettable      : True
# TypeNameOfValue : System.Int32
# Name            : b
# IsInstance      : True
# 
# Value           : 2
# MemberType      : NoteProperty
# IsSettable      : True
# IsGettable      : True
# TypeNameOfValue : System.Int32
# Name            : c
# IsInstance      : True
```

## 参考
- [PSObject Class (System.Management.Automation) | Microsoft Docs](https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.psobject?view=powershellsdk-7.0.0)
- [PSCustomObject Class (System.Management.Automation) | Microsoft Docs](https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.pscustomobject?view=powershellsdk-7.0.0)
- [PSCustomObject について知りたかったことのすべて](https://docs.microsoft.com/ja-jp/powershell/scripting/learn/deep-dives/everything-about-pscustomobject?view=powershell-7)：PSCustomObjectクラスがPSObject非表示プロパティを持つことの説明。

# PSCustomObjectのパイプラインで渡されるオブジェクトは元のPSCustomObject

`PSCustomObject`をパイプライン演算子`|`で次の関数に渡したとき、関数は元の`PSCustomObject`そのものを受け取ります。したがって、キーと値ペアの配列を扱いたいときは`PSObject`非表示プロパティを介します。

```powershell
$obj = [PSCustomObject]@{a=0; b=1; c=2}
$obj | Select-Object {$_}
# $_
# --
# @{a=0; b=1; c=2}

$obj | Select-Object {$_.GetType()}
# $_.GetType()
# ------------
# System.Management.Automation.PSCustomObject
```

# 配列に型を指定する。

かっこ付きのカンマ演算子による配列作成`(a, b, ...)`または配列部分式演算子`@(a, b, ...)`の前にキャスト`[type[]]`を指定することで配列に型を指定できます。

```powershell
$Array1 = [int[]](0, 1, 2)
#$Array1 = [int[]]@(0, 1, 2)
$Array1
# 0
# 1
# 2
$Array1.GetType().Name
# Int32[]
```

かっこを省略した場合は挙動が変わることに注意してください。

```powershell
$Array1 = [int[]]0, 1, 2
$Array1
# Length         : 1
# LongLength     : 1
# Rank           : 1
# SyncRoot       : {0}
# IsReadOnly     : False
# IsFixedSize    : True
# IsSynchronized : False
# Count          : 1
# 
# 1
# 2
$Array1.GetType().Name
# Object[]
```

```powershell
$Array1 = [int[]], 0, 1, 2
$Array1
# IsPublic IsSerial Name                                     BaseType
# -------- -------- ----                                     --------
# True     True     Int32[]                                  System.Array
# 0
# 1
# 2
$Array1.GetType().Name
# Object[]
```

連番の場合は`..`も使えます。

```powershell
$Array1 = [int[]](0..2)
```

# Select-Objectでスクリプトブロックを与えたときの結果に名前を付ける

`Select-Object`にスクリプトブロック`{...}`を渡すとCalculated propertyが得られます。Calculated propertyは列名が式そのものとなり複雑です。

```powershell
#0..3 | Select-Object {$_ + 1}
# $_ + 1
# ------
# 1
# 2
# 3
# 4
```

`Select-Object`に`label`または`l`キーに名前、`expression`または`e`にスクリプトブロックを持つハッシュテーブルを渡すと名前を指定してスクリプトブロックの結果を取得できます。

```powershell
0..3 | Select-Object @{l="Value"; e={$_ + 1}}
# Value
# -----
#     1
#     2
#     3
#     4
```

配列への変換も簡単です。

```powershell
(0..3 | Select-Object @{l="Value"; e={$_ + 1}}).Value
# 1
# 2
# 3
# 4
```

## 参考

- [Select-Object (Microsoft.PowerShell.Utility) - PowerShell | Microsoft Docs](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/select-object?view=powershell-7)