2026年02月24日 PowershellでのCSVとXMLの扱い方 [長年日記]
_ PowershellでのCSVの扱い方
ヘッダーありCSVを表示
> Get-Content .\test_header.csv name,email,tel,age 伊藤 太郎,taro@foo.org,090-1111-1111,23 伊藤 次郎,jiro@foo.org,090-2222-2222,22 伊藤 三郎,saburo@foo.org,090-3333-3333,22 伊藤 四郎,siro@foo.org,090-4444-4444,22 伊藤 五郎,goro@foo.org,090-5555-5555,20 伊藤 花子,hanako@foo.org,,9
ヘッダーありCSVをCSVオブジェクトとして取込み
> $csv = (Get-Content test_header.csv | ConvertFrom-Csv) > $csv name email tel age ---- ----- --- --- 伊藤 太郎 taro@foo.org 090-1111-1111 23 伊藤 次郎 jiro@foo.org 090-2222-2222 22 伊藤 三郎 saburo@foo.org 090-3333-3333 22 伊藤 四郎 siro@foo.org 090-4444-4444 22 伊藤 五郎 goro@foo.org 090-5555-5555 20 伊藤 花子 hanako@foo.org 9
CSVオブジェクトから項目「name」「tel」を取り出し
> $csv | select-object name,tel name tel ---- --- 伊藤 太郎 090-1111-1111 伊藤 次郎 090-2222-2222 伊藤 三郎 090-3333-3333 伊藤 四郎 090-4444-4444 伊藤 五郎 090-5555-5555 伊藤 花子
CSVオブジェクトから先頭2行を取り出し
> $csv | select-object name,tel -first 2 name tel ---- --- 伊藤 太郎 090-1111-1111 伊藤 次郎 090-2222-2222
CSVオブジェクトから最終2行を取り出し
> $csv | select-object name,email -last 2 name email ---- ----- 伊藤 五郎 goro@foo.org 伊藤 花子 hanako@foo.org
CSVオブジェクトから先頭2行をスキップして、そこから先頭1行取り出し
> $csv | select-object name,email -skip 2 -first 1 name email ---- ----- 伊藤 三郎 saburo@foo.org
CSVオブジェクトから「name」の末尾が「次郎」と「email」の先頭が「taro」の行を抽出
> $csv | where-object{$_.name -match "次郎$" -or $_.email -match "^taro"}
name email tel age
---- ----- --- ---
伊藤 太郎 taro@foo.org 090-1111-1111 23
伊藤 次郎 jiro@foo.org 090-2222-2222 22
CSVオブジェクトを「age」の昇順、「tel」の降順にソート⇒「age」の昇順にならない!?
> $csv | sort-object -property @{expression={$_.age}},@{expression={$_.tel};desc=$true}
name email tel age
---- ----- --- ---
伊藤 五郎 goro@foo.org 090-5555-5555 20
伊藤 四郎 siro@foo.org 090-4444-4444 22
伊藤 三郎 saburo@foo.org 090-3333-3333 22
伊藤 次郎 jiro@foo.org 090-2222-2222 22
伊藤 太郎 taro@foo.org 090-1111-1111 23
伊藤 花子 hanako@foo.org 9
CSVオブジェクトを「age」の昇順、「tel」の降順にソート⇒今度はOK!
> $csv | sort-object -property @{expression={[decimal]$_.age}},@{expression={$_.tel};desc=$true}
name email tel age
---- ----- --- ---
伊藤 花子 hanako@foo.org 9
伊藤 五郎 goro@foo.org 090-5555-5555 20
伊藤 四郎 siro@foo.org 090-4444-4444 22
伊藤 三郎 saburo@foo.org 090-3333-3333 22
伊藤 次郎 jiro@foo.org 090-2222-2222 22
伊藤 太郎 taro@foo.org 090-1111-1111 23
CSVオブジェクトをCSVに変換
> $csv | convertto-csv !!TYPE System.Management.Automation.PSCustomObject "name","email","tel","age" "伊藤 太郎","taro@foo.org","090-1111-1111","23" "伊藤 次郎","jiro@foo.org","090-2222-2222","22" "伊藤 三郎","saburo@foo.org","090-3333-3333","22" "伊藤 四郎","siro@foo.org","090-4444-4444","22" "伊藤 五郎","goro@foo.org","090-5555-5555","20" "伊藤 花子","hanako@foo.org","","9"
CSVオブジェクトをCSVに変換(「#TYPE System.Management.Automation.PSCustomObject」の行は省略)
> $csv | convertto-csv -NoTypeInformation "name","email","tel","age" "伊藤 太郎","taro@foo.org","090-1111-1111","23" "伊藤 次郎","jiro@foo.org","090-2222-2222","22" "伊藤 三郎","saburo@foo.org","090-3333-3333","22" "伊藤 四郎","siro@foo.org","090-4444-4444","22" "伊藤 五郎","goro@foo.org","090-5555-5555","20" "伊藤 花子","hanako@foo.org","","9"
ヘッダーなしCSVを表示
> Get-Content .\test_noheader.csv 伊藤 太郎,taro@foo.org,090-1111-1111,23 伊藤 次郎,jiro@foo.org,090-2222-2222,22 伊藤 三郎,saburo@foo.org,090-3333-3333,22 伊藤 四郎,siro@foo.org,090-4444-4444,22 伊藤 五郎,goro@foo.org,090-5555-5555,20 伊藤 花子,hanako@foo.org,,9
ヘッダーなしCSVをCSVオブジェクトとして取込み⇒1行目がヘッダーとして認識されている!?
> $csv = (Get-Content test_noheader.csv | ConvertFrom-Csv) > $csv 伊藤 太郎 taro@foo.org 090-1111-1111 23 ---------- ------------ ------------- -- 伊藤 次郎 jiro@foo.org 090-2222-2222 22 伊藤 三郎 saburo@foo.org 090-3333-3333 22 伊藤 四郎 siro@foo.org 090-4444-4444 22 伊藤 五郎 goro@foo.org 090-5555-5555 20 伊藤 花子 hanako@foo.org 9
ヘッダーなしCSVをヘッダーを指定してCSVオブジェクトとして取込み⇒ヘッダーが正しく認識されている!
> $csv = (Get-Content test_noheader.csv | ConvertFrom-Csv -header @("name","email","tel","age"))
> $csv
name email tel age
---- ----- --- ---
伊藤 太郎 taro@foo.org 090-1111-1111 23
伊藤 次郎 jiro@foo.org 090-2222-2222 22
伊藤 三郎 saburo@foo.org 090-3333-3333 22
伊藤 四郎 siro@foo.org 090-4444-4444 22
伊藤 五郎 goro@foo.org 090-5555-5555 20
伊藤 花子 hanako@foo.org 9
_ PowershellでのXMLの扱い方
サンプルXML(test.xml)の表示
> Get-Content .\test.xml
<?xml version="1.0" encoding="UTF-8"?>
<root>
<record id="1">
<name version="1">伊藤 太郎</name>
<email>ito-taro@foo.org</email>
<tel>090-1234-1111</tel>
<detail><![CDATA[<?xml version="1.0" encoding="UTF-8"?><root><birthday>2001/01/01</birthday></root>]]></detail>
</record>
<record id="2">
<name version="1">伊藤 次郎</name>
<email>ito-jiro@foo.org</email>
<tel>090-1234-2222</tel>
<detail><![CDATA[<?xml version="1.0" encoding="UTF-8"?><root><birthday>2002/02/02</birthday></root>]]></detail>
</record>
<record id="3">
<name version="1">伊藤 三郎</name>
<email>ito-saburo@foo.org</email>
<tel>090-1234-3333</tel>
<detail><![CDATA[<?xml version="1.0" encoding="UTF-8"?><root><birthday>2003/03/03</birthday></root>]]></detail>
</record>
</root>
サンプルXML(test.xml)をXMLオブジェクト($xml1)に取込み
> [xml]$xml1 = Get-Content .\test.xml
XMLオブジェクトを表示
> $xml1 xml root --- ---- version="1.0" encoding="UTF-8" root
XMLオブジェクトのノード(xml)を表示
> $xml1.xml version="1.0" encoding="UTF-8"
XMLオブジェクトのノード(root)を表示
> $xml1.root
record
------
{name, name, name}
XMLオブジェクトのノード(record)を表示
> $xml1.root.record id : 1 name : name email : ito-taro@foo.org tel : 090-1234-1111 detail : detail id : 2 name : name email : ito-jiro@foo.org tel : 090-1234-2222 detail : detail id : 3 name : name email : ito-saburo@foo.org tel : 090-1234-3333 detail : detail
XMLオブジェクトのノード(record)の2番目を表示
> $xml1.root.record[1] id : 2 name : name email : ito-jiro@foo.org tel : 090-1234-2222 detail : detail
XMLオブジェクトのノード(name)を表示
> $xml1.root.record.name version #text ------- ----- 1 伊藤 太郎 1 伊藤 次郎 1 伊藤 三郎
XMLオブジェクトのノード(name)の値を表示
> $xml1.root.record.name.'#text' 伊藤 太郎 伊藤 次郎 伊藤 三郎
XMLオブジェクトのノード(detail)を表示
> $xml1.root.record.detail #cdata-section -------------- <?xml version="1.0" encoding="UTF-8"?><root><birthday>2001/01/01</birthday></root> <?xml version="1.0" encoding="UTF-8"?><root><birthday>2002/02/02</birthday></root> <?xml version="1.0" encoding="UTF-8"?><root><birthday>2003/03/03</birthday></root>
XMLオブジェクトのノード(detail)の値を表示
> $xml1.root.record.detail.'#cdata-section' <?xml version="1.0" encoding="UTF-8"?><root><birthday>2001/01/01</birthday></root> <?xml version="1.0" encoding="UTF-8"?><root><birthday>2002/02/02</birthday></root> <?xml version="1.0" encoding="UTF-8"?><root><birthday>2003/03/03</birthday></root>
XMLオブジェクトのノード(record)の属性(id)を表示
> $xml1.root.record.id 1 2 3
XMLオブジェクトのノード(record)を検索して表示
> $xml1.root.record | where-object{$_.name.'#text' -eq "伊藤 次郎"}
id : 2
name : name
email : ito-jiro@foo.org
tel : 090-1234-2222
detail : detail
XMLオブジェクトのノード(record)から「伊藤 次郎」を検索して、「伊藤 花子」に変更
> $record1 = $xml1.root.record | where-object{$_.name.'#text' -eq "伊藤 次郎"}
> $record1.name.'#text' = "伊藤 花子"
> $xml1.root.record.name
version #text
------- -----
1 伊藤 太郎
1 伊藤 花子
1 伊藤 三郎
XMLオブジェクトのノード(record)から「伊藤 花子」を検索して、入れ子のXMLオブジェクト内のbirthdayを変更
> $record2 = $xml1.root.record | where-object{$_.name.'#text' -eq "伊藤 花子"}
> [xml]$xml2 = $record2.detail.'#cdata-section'
> $xml2.root.birthday = "2002/01/23"
> $record2.detail.'#cdata-section' = $xml2.outerXML
> $xml1.root.record.detail
#cdata-section
--------------
<?xml version="1.0" encoding="UTF-8"?><root><birthday>2001/01/01</birthday></root>
<?xml version="1.0" encoding="UTF-8"?><root><birthday>2002/01/23</birthday></root>
<?xml version="1.0" encoding="UTF-8"?><root><birthday>2003/03/03</birthday></root>
「id」が「2」のnode(レコード)を指定して削除する
> $recordToRemove = $xml1.root.record | where-object{$_.id -eq "2"}
> $xml1.root.RemoveChild($recordToRemove)
id : 2
name : name
email : ito-jiro@foo.org
tel : 090-1234-2222
detail : detail
上記の削除結果を確認する
> $xml1.root.record id : 1 name : name email : ito-taro@foo.org tel : 090-1234-1111 detail : detail id : 3 name : name email : ito-saburo@foo.org tel : 090-1234-3333 detail : detail
ノード(record)を作成し、属性(id)に「4」をセットする
> $record = $xml1.CreateElement("record")
> $record.SetAttribute("id","4")
> $record
id
--
4
ノード(name)を作成し、属性(version)に「1」をセットし、値に「伊藤 四郎」をセットする
> $name = $xml1.CreateElement("name")
> $name.SetAttribute("version","1")
> $name.innerXML = "伊藤 四郎"
> $name
version #text
------- -----
1 伊藤 四郎
ノード(email)を作成し、値に「ito-siro@foo.org」をセットする
> $email = $xml1.CreateElement("email")
> $email.innerXML = "ito-siro@foo.org"
> $email
#text
-----
ito-siro@foo.org
ノード(tel)を作成し、値に「090-1234-4444」をセットする
> $tel = $xml1.CreateElement("tel")
> $tel.innerXML = "090-1234-4444"
> $tel
#text
-----
090-1234-4444
ノード(record)にノード(name)を追加する
> $record.AppendChild($name) version #text 1 伊藤 四郎
ノード(record)にノード(email)を追加する
> $record.AppendChild($email) #text ito-siro@foo.org
ノード(record)にノード(tel)を追加する
> $record.AppendChild($tel) #text 090-1234-4444
ノード(record)の内容を確認する
> $record id name email tel -- ---- ----- --- 4 name ito-siro@foo.org 090-1234-4444
ノード(root)にノード(record)を追加する
> $xml1.root.AppendChild($record) id name email tel -- ---- ----- --- 4 name ito-siro@foo.org 090-1234-4444
ノード(root)にノード(record)が追加されたことを確認する
> $xml1.root.record id : 1 name : name email : ito-taro@foo.org tel : 090-1234-1111 detail : detail id : 3 name : name email : ito-saburo@foo.org tel : 090-1234-3333 detail : detail id : 4 name : name email : ito-siro@foo.org tel : 090-1234-4444
いろいろ更新したXMLオブジェクトを「test2.xml」にセーブ
> $xml1.Save("$pwd/test2.xml")
更新したXML(test2.xml)を表示
> Get-Content .\test2.xml
<?xml version="1.0" encoding="UTF-8"?>
<root>
<record id="1">
<name version="1">伊藤 太郎</name>
<email>ito-taro@foo.org</email>
<tel>090-1234-1111</tel>
<detail><![CDATA[<?xml version="1.0" encoding="UTF-8"?><root><birthday>2001/01/01</birthday></root>]]></detail>
</record>
<record id="3">
<name version="1">伊藤 三郎</name>
<email>ito-saburo@foo.org</email>
<tel>090-1234-3333</tel>
<detail><![CDATA[<?xml version="1.0" encoding="UTF-8"?><root><birthday>2003/03/03</birthday></root>]]></detail>
</record>
<record id="4">
<name version="1">伊藤 四郎</name>
<email>ito-siro@foo.org</email>
<tel>090-1234-4444</tel>
</record>
</root>
[ツッコミを入れる]