Powershellでいろいろな形式の設定ファイルを読み込む(*.properties, *.xml, *.json, *.csv)

主題の通り、Powershellを使用した設定ファイルの読み込んで変数に格納して使う方法のメモ。 日本語でググってもまとまった情報がないのでまとめる。

環境

PS C:\> #OSのVersion
PS C:\> "$((get-wmiobject win32_operatingsystem).caption) ($((get-wmiobject win32_operatingsystem).version))"
Microsoft Windows 10 Pro (10.0.10586)

PS C:\> #Powershellのバージョン
PS C:\> $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
5      0      10586  122   

設定ファイルの読み込み方

propertiesファイル

key=valueな形式のファイルから値を読み取る場合にはConvertFrom-StringDataコマンドレットを利用する*1

PS C:\> #設定ファイル($confPath)のファイルを読み込み、連想配列に変換する
PS C:\> $conf = Get-Content $confPath -Raw | ConvertFrom-StringData

PS C:\> #設定ファイル($confPath)の内容が連想配列(Hashtable)に格納されていることを確認する
PS C:\> $conf.GetType()

IsPublic IsSerial Name                                     BaseType                               
-------- -------- ----                                     --------                               
True     True     Hashtable                                System.Object                          



PS C:\> #keyに対応する値の取り出し
PS C:\> $conf.key
value

PS C:\> #key名に'.'が入っているときはエスケープする
PS C:\> $conf.'hoge.key'
value

XMLファイル

XMLファイルから値を読み取る場合にはxml型にキャストする。*2 *3

PS C:\> #変数をxml型に指定してファイルを読み込む
PS C:\> [xml]$conf = Get-Content $confPath

PS C:\> #型を確認するとXmlDocument型に格納されている
PS C:\> $conf.GetType()

IsPublic IsSerial Name                                     BaseType                               
-------- -------- ----                                     --------                               
True     False    XmlDocument                              System.Xml.XmlNode   

PS C:\> #読んでみる
PS C:\> $conf.catalog

book                       
----                       
{book, book, book, book...}


PS C:\> #配列要素は以下のようにアクセス可能
PS C:\> $conf.catalog.book[0].id
bk101

PS C:\> #こんな書き方でも読み込める
PS C:\> $conf = [xml](Get-Content $confPath)

参考

JSONファイル

JSON形式のファイルから値を読み取る場合にはConvertFrom-Jsonコマンドレットを利用する*4

以下のような設定ファイルがあったとする。

{ "Address": 0, "AddressFamily": 2, "ScopeId": null, "IsIPv6Multicast": false, "IsIPv6LinkLocal": false, "IsIPv6SiteLocal": false, "IsIPv6Teredo": false, "IsIPv4MappedToIPv6": false, "IPAddressToString": "0.0.0.0" }

PowerShell で JSON をファイル入出力 する - tech.guitarrapc.cóm

上記の読み込みは以下のように書ける

PS C:\> #ConvertFrom-JsonでJsonを変数に格納する
PS C:\> $conf = Get-Content $confPath | ConvertFrom-Json

PS C:\> #型を調べてみると、PSCustomObject型で格納される。
PS C:\> $conf.GetType()

IsPublic IsSerial Name                                     BaseType                                                          
-------- -------- ----                                     --------                                                          
True     False    PSCustomObject                           System.Object                                                     



PS C:\> #値へのアクセスはPowershellでよくある感じでOK
PS C:\> $conf.Address
0

CSVファイル

CSV形式のファイルから値を読み取る場合にはConvertFrom-Csvコマンドレットを利用する*5 以下のような設定ファイルがあったとする

value1-1,value2-1,value3-1
value1-2,value2-2,value3-2

上記の読み込みは以下のように書ける

PS C:\> #値の読み込み
PS C:\> $conf = Get-Content $confPath | ConvertFrom-Csv -Header "name1","name2","name3"

PS C:\> #Objectの配列に値が格納される。
PS C:\> $conf.GetType()

IsPublic IsSerial Name                                     BaseType                               
-------- -------- ----                                     --------                               
True     True     Object[]                                 System.Array  

PS C:\> #特定列のみ取り出す。
PS C:\> $conf.name1
value1-1
value1-2

PS C:\> #特定行のみ取り出す。
PS C:\> $conf[0]

name1    name2    name3   
-----    -----    -----   
value1-1 value2-1 value3-1


PS C:\> #特定の値へのアクセス
PS C:\> $conf[0].name1
value1-1

Delimiterパラメーターで区切り記号を指定したりできる また、Headerパラメーターを指定しない場合は一行目がヘッダとして扱われる。

※Import-Csvというコマンドもあるが、個人的にConvertFrom*でそろえたほうがシェルが読みやすいと思うのでこちらを推奨。

その他

整理してみた感想は以下の通り。

  • シェルの設定ファイル程度であればPropetiesファイルが直感的にかけて楽そう*6

  • JSONCSVXMLは、内容を構造化できるので、設定ファイルというよりはデータを扱うために使うとよさそう。

*1:互換性確認はしていないがpowershell -v 1 でもコマンドは存在する

*2:powershell -v 1 しても動く

*3:使用したxmlはMSのサンプル サンプル XML ファイル (books.xml)

*4:互換性確認はしていないがpowershell -v 3 以降でコマンドは存在する

*5:互換性確認はしていないがpowershell -v 1 以降でコマンドは存在する

*6:複雑な設定が必要ならXMLという手もあるが、そんな複雑なシェルは作るべきではないと思う。JSONCSVはコメントが入れられないのでダメ