概要
PowerShellにはYAMLを読み書きする標準ライブラリが現時点でないが、標準ライブラリ以外であればいくつかこれが可能なライブラリは存在している。そのうちの一つであるpowershell-yamlモジュールを使い、PowerShell 7.1.3上で以下ができることを確認した。
-
ConvertTo-YAML $Hashtable
PowerShellオブジェクトからYAML文字列に変換する。 -
ConvertTo-YAML $OrderedDictionary
PowerShellオブジェクトからYAML文字列に変換する。変換対象変数がOrderedDictionary
型の場合、キー順序は維持される。 -
ConvertFrom-YAML $String
YAML文字列からPowerShellオブジェクトに変換する。 -
ConvertFrom-YAML $String -Ordered
YAML文字列からPowerShellオブジェクトに変換する。-Ordered
が指定された場合、キー順序は維持される(返り値がOrderedDictionary
型になる)。
詳細
PowerShellのYAML対応状況
PowerShellの標準モジュールでは、現在のところYAML
を扱うためのものはない。
PS> Get-Command -Noun YAML
PS>
GitHubのPowerShellリポジトリでは2017年からいまだにこの点の議論がされている(つまり標準モジュールがないまま要望が続けられている)ようだ。
ユーザーによる実装は複数あり、Google検索するとまず「PowershellでYAMLを扱う(Import-YAML) - Qiita」が出てきたりもするが、YAMLの読み込み(Import-YAML
)だけでなく対になるYAMLを生成するコマンドレットも欲しい。Find-Module
すると次のように複数のモジュールが見つかる。
PS> Find-Module -Name "*YAML*"
Version Name Repository Description
------- ---- ---------- -----------
0.4.2 powershell-yaml PSGallery Powershell module for serializing and d...
1.0.3 FXPSYaml PSGallery PowerShell module used to intrepret Yam...
0.2.0 Gainz-Yaml PSGallery Gainz: Yaml…
0.1.0 Gz-Yaml PSGallery # Gz-Yaml…
1.0.0 Pode.Yaml PSGallery A YAML Request and Response parser exte...
1.0 PSYamlQuery PSGallery PowerShell wrapper for yq.exe, enables ...
1.4 WSDLToYAML PSGallery Parse WSDL, extract the model and gener...
上記のGitHubイシューからリンクをたどっていって「Josep - A Brief introduction to YAML in Powershell」に辿りついた。2018年のブログエントリで、コンパクトにこうした概況をまとめたうえで、以下の2モジュールについて説明している。
- PSYaml: A Powershell module to convert YAML documents to and from PowerShell objects
- powershell-yaml: PowerShell CmdLets for YAML format manipulation
パッと見て気付いたことがある。リポジトリの更新日時はPSYamlが2019年9月11日、powershell-yamlは2020年5月5日で後者の方がより最近まで更新されている。一方でpowershell-yamlはREADMEの冒頭にYamlDotNetのラッパーだと書かれており、.NET版のWindows PowerShellではなく現在のPowerShell Coreで動くかちょっと不安だ。
This powershell module is a thin wrapper on top of YamlDotNet that serializes and un-serializes simple powershell objects to and from YAML.
でもそういえば、PowerShell 7.1.3の手元の環境でもFind-Module
に出てきた。まずはpowershell-yamlが動作するか、手を動かして確認することに決める。
powershell-yamlのインストール
まずあらためて環境について確認しておくと、Windows上のPowerShell 7.1.3。リポジトリとしてはPSGelleryのみを登録している。
PS> $PSVersionTable | select PSVersion, PSEdition, OS
PSVersion PSEdition OS
--------- --------- --
7.1.3 Core Microsoft Windows 10.0.19041
PS> Get-PSRepository
Name InstallationPolicy SourceLocation
---- ------------------ --------------
PSGallery Trusted https://www.powershellgallery.com/api/v2
インストールは通常通り Install-Module powershell-yaml
でよい。やらなくてもいいけど、一応 Get-Module
でインストールされたこととバージョンの確認もしておく。
PS> Install-Module powershell-yaml
PS> Get-Module powershell-yaml
ModuleType Version PreRelease Name ExportedCommands
---------- ------- ---------- ---- ----------------
Script 0.4.2 powershell-yaml {ConvertFrom-Yaml, ConvertTo-Yaml, cfy, cty}
YAMLへの変換(ConvertTo-Yaml)
まずYAML文字列への変換。READMEにあったサンプルデータを使うことにする。
PS> $data = @{"hello"="world"; "anArray"=@(1,2,3); "nested"=@{"array"=@("this", "is", "an", "array")}}
PS> $data
Name Value
---- -----
hello world
nested {array}
anArray {1, 2, 3}
YAML文字列に変換し、結果を確認する。
PS> $yaml = ConvertTo-Yaml $data
PS> $yaml
hello: world
nested:
array:
- this
- is
- an
- array
anArray:
- 1
- 2
- 3
変換できている。
キー順序を維持したYAMLへの変換(OrderedDictionaryのConvertTo-Yaml)
先の例では $data
には hello
anArray
nested
の順にキーを作成したはずだけど、YAML文字列ではこの順序が変わっている。ただそれ以前に $data
を表示した時にすでに変わっていた。 $data
をキーの順序を保持する OrderedDictionary
にした場合の動作も確認してみた。
サンプルデータを OrderedDictionary
として作成する。
PS> $data = [ordered]@{"hello"="world"; "anArray"=@(1,2,3); "nested"=@{"array"=@("this", "is", "an", "array")}}
PS> $data
Name Value
---- -----
hello world
anArray {1, 2, 3}
nested {array}
YAML文字列に変換し、結果を確認する。
PS> $yaml = ConvertTo-Yaml $data
PS> $yaml
hello: world
anArray:
- 1
- 2
- 3
nested:
array:
- this
- is
- an
- array
OrderdDictionaryのキー順序と一致したYAML文字列が得られてる。
YAMLからの変換(ConvertFrom-Yaml)
先ほどのYAML文字列を対象として、PowerShellオブジェクトに変換させることにする。
PS> $yaml
hello: world
anArray:
- 1
- 2
- 3
nested:
array:
- this
- is
- an
- array
PowerShellオブジェクトに変換し、結果を確認する。
PS> $data = ConvertFrom-Yaml $yaml
PS> $data
Name Value
---- -----
hello world
nested {array}
anArray {1, 2, 3}
変換できていた。ただしキーの順序は保持されてない。型も確認しておく。
PS> $data | Get-Member
TypeName: System.Collections.Hashtable
Name MemberType Definition
---- ---------- ----------
(略)
返り値は Hashtable
型になっていた。
キー順序を維持したYAMLからの変換(ConvertFrom-Yaml -Ordered)
「Josep - A Brief introduction to YAML in Powershell」の中で -Ordered
オプションが紹介されていたので、試してみる。対象は同じYAML文字列とする。
PS> $yaml
hello: world
anArray:
- 1
- 2
- 3
nested:
array:
- this
- is
- an
- array
PowerShellオブジェクトに変換し、結果を確認する。
PS> $data = ConvertFrom-Yaml $yaml -Ordered
PS> $data
Name Value
---- -----
hello world
anArray {1, 2, 3}
nested {array}
キーの順序を維持して変換できていた。型も確認しておく。
PS> $data | Get-Member
TypeName: System.Collections.Specialized.OrderedDictionary
Name MemberType Definition
---- ---------- ----------
(略)
返り値は OrderedDictionary
型になっていた。