PowerShellでImport-Csvおよびその他のCSVコマンドをマスターする方法

PowerShellのExport-CsvコマンドレットとPowerShellのImport-Csvコマンドレットを使用すると、管理者はforeachループを介してCSVをインポートしたり、Export-Csvを使用してCSVに追記したり、配列をCSVファイルにエクスポートしたりすることができます。

この記事では、PowerShellを使用してCSVを管理するための一般的なシナリオについて学びます。具体的には、以下のようなことがあります:

  • PowerShellでCSVファイルを読み込む
  • PowerShellでCSVファイルを保存する
  • Export-CSVを実行する前に出力を整形する
  • CSVに追記する
  • 既存のファイルに差分を追記する
  • Export-CSV#TYPE文字列

CSVファイルの内部構造に馴染みがない場合は、CSVファイルはテーブル内の値を文字通りコンマで区切るという標準的な形式に従うテキストファイルです。 Export-Csvコマンドレットを使用して、PowerShellでCSVファイルを作成し、1つ以上のオブジェクトをそれにパイプすることができます。

以下のコマンドは、最初の2つの実行中のプロセスを見つけ、生成されたオブジェクトをExport-Csvコマンドレットに渡します。 Export-Csvコマンドレットは、CSVファイルprocesses.csvをシステムドライブのルート(おそらくC:\)に作成します。

PS51> Get-Process | Select-Object -First 2 | Export-CSV -Path "$env:SystemDrive\processes.csv"

今、メモ帳でprocesses.csvを開いてください。ヘッダーとして"Name","SI","Handles","VM"が先頭に表示されるはずです。また、#TYPE System.Diagnostics.Processも表示されますが、この文字列は現時点ではあまり意味がありません。心配しないでください、この記事で詳しく説明します。

Import-Csvを使用してCSVファイルを読み取る

このようなヒントがもっと欲しいですか?私の個人のPowerShellブログをチェックしてください。

PowerShellには、テキストファイルを読み取るためのいくつかのコマンドがあります。それらのコマンドは、Get-ContentImport-Csvです。これらの2つのコマンドレットは、技術的には同じ方法でファイルを読み取ります。ただし、Import-Csvは一歩進んでいます。 Import-Csvは、テキストファイルだけでなく、CSVファイルの基礎的な構造も理解します。

CSVファイルは特定のスキーマに従うため、Import-CsvはCSVスキーマを理解しています。このコマンドレットはディスクからテキストファイルを読み取るだけでなく、CSVファイル内の行をPowerShellオブジェクトに変換します。

非CSVファイル

通常、CSVのデータはカンマで区切られますが、別の区切り文字でデータが区切られている場合もあります。この区切り文字は、タブまたはセミコロンであることがあります。

CSVファイルの区切り文字が異なる場合、Delimiterパラメーターを使用することができます。このパラメーターは、Import-Csvに対して、デフォルトでカンマを検索する代わりに、別の値を検索するように指示します。

例えば、タブ区切りのファイルがある場合、以下のようにファイルを読み取ることができます:

PS51> Import-Csv -Path tab-separated-data.csv -Delimiter "`t"

ヘッダーの追加

A common Import-Csv parameter is Header. This parameter lets you specify the property names of the objects created by this cmdlet.

デフォルトでは、Import-CsvコマンドレットはCSVファイルの最初の行をヘッダーと見なします。そして、これらの値を各行(オブジェクト)のプロパティに変換します。しかし、ヘッダー行がないCSVファイルがある場合、Headerパラメーターを使用して自分で定義することができます。

Headerパラメーターは、Import-CSVが最初の行をヘッダーとして使用しないようにし、ヘッダーを手動でCSVファイルに追加する手間を省くことができます。

この動作を示すために、メモ帳を開き、以下のテキストをコピーして貼り付けてください。このテキストは、3つの行と2つの列を持つデータセットを表します。

a,1
b,2
c,3

テキストファイルをtest.csvとして保存してください。拡張子を有効にするか、ファイルを二重引用符で囲んで保存し、.csv.txtで終わるようなファイルに誤って保存しないように注意してください。

そして、Headerパラメーターなしで最近作成したCSVファイルを読み取るために、Import-CSVを使用し、出力を調べてください。

PS51> Import-Csv .\test.csv

a 1
---
b 2
c 3

最初の行をオブジェクトのプロパティとして使用していることに注意してください。 A1 は、オブジェクトのプロパティとして望ましい「ラベル」ではありません。 Abc は文字であり、123 は数字です。以下のように Header パラメータでそれらを定義する必要があります:

PS51> Import-Csv .\test.csv -Header "Letter", "Number"

Letter Number
------ ------
a      1
b      2
c      3

PowerShell で CSV ファイルを保存する

PowerShell オブジェクトから CSV ファイルを作成または保存する必要がある場合、他の方法もあります。 Import-Csv コマンドレットは CSV ファイルを PowerShell オブジェクトに「変換」しますが、Export-Csv はその逆を行います。このコマンドレットは PowerShell オブジェクトを CSV ファイルに「変換」します。

Export-Csv を使用して CSV ファイルを保存することで、後でそのデータを他のシステムで表示したり使用したりすることができます。

例えば、Get-ProcessExport-Csv コマンドレットにパイプしてコンピュータ上で実行中のすべてのプロセスを保存することができます。

PS51> Get-Process | Export-Csv -Path processes.csv

Export-Csv コマンドレットは単純な性質を持っていますが、いくつかの落とし穴に注意する必要があります。

Export-CSV を実行する前に出力を整形する

上記で見たように、Export-Csv は「生の」変換を行います。特別なリッチテキストの書式設定や色の追加は行いません。

最も一般的な落とし穴の1つは、CSV にエクスポートする前に出力を見栄え良くするために試みることです。多くのユーザーは、CSV にエクスポートする前に出力をより良く見せようと試みるでしょう。しかし、それは事態を悪化させることになることをお見せします。

Microsoft ExcelでCSVファイルを開き、イタリック体や太字、色などを追加することができますが、ファイルをCSV形式で保存すると、すべての書式設定が削除されます。CSVファイルは単なるテキストファイルであり、カンマ(またはタブ)で区切られた値が含まれているだけです。

CSVファイルは単なるテキストファイルです。Import-CsvFormat-* PowerShellコマンドレットにパイプすると、期待どおりには動作しません。

MicrosoftのExport-Csvのドキュメントによれば、「Export-Csvコマンドレットに送信する前にオブジェクトを書式設定しないでください。書式設定されたオブジェクトをExport-CSVに渡すと、CSVファイルにはオブジェクトのプロパティではなく、書式設定のプロパティが含まれます。」

なぜなのでしょうか?

PowerShellウィンドウを開き、ダミーデータを作成してください。この記事の最初のセクションでカバーされているGet-Processの例を使用しましょう。ただし、今回は出力を変数に割り当てます。そして、これらのプロセスオブジェクトをFormat-Tableコマンドレットにパイプしてください。

PS51> $a = Get-Process
PS51> $a | Format-Table
Using Format-Table

Format-Tableを使用すると、きれいな表形式の出力が得られます。

この出力を別の変数に保存してください。

PS51> $b = $a | Format-Table

次に、$a$bの変数値のプロパティをGet-Memberで表示してください。このコマンドレットは、なぜこれらの2つのオブジェクトがCSVファイルに同じ方法でエクスポートされないのかを理解するのに役立ちます。

PS51> $a | Get-Member
System.Diagnostics.Process object type
PS51> $b | Get-Member
Format-Table‘s many object types

Get-Processからの直接の出力は、TypeName: System.Diagnostics.Process となります。一方、Format-Tableの出力は全く異なります。さまざまな種類のプロパティを持つさまざまなタイプが返されます。

コンソールで$a$bを表示すると、出力は同じに見えるでしょう。この動作は、PowerShellのフォーマットシステムによるものです。

Export-Csvの出力にはどのような影響がありますか?

PS51> $b | Export-Csv | Format-Table

Export-Csvは、各オブジェクトをそのまま読み込みます。出力をFormat-*のコマンドレットにパイプすると、Export-Csvが受け取る入力が変更されます。これにより、新しいCSVファイルに保存される出力に影響が出ます。

Export-Csvに出力をパイプする場合は、Format-*のコマンドレットに出力をパイプしないでください。

CSVはデータに焦点を当てており、フォーマットは重要ではありません。

CSVファイルへの追加

新しく作成するのではなく、既存のファイルに追加する必要がある場合もあります。Export-Csvは、デフォルトではPathパラメータで指定されたファイルを上書きします。

CSVにデータを追加する必要がある場合は、Appendパラメータを使用してください。

CSV ファイルに各処理されたオブジェクトを保存したいループがあるとしましょう。各イテレーションごとに、CSV ファイルに保存したい異なるオブジェクトがあります。繰り返し Export-Csv を呼び出すと、Append パラメーターを使用しない場合、CSV ファイルは上書きされます。Append パラメーターを使用しないと、通常は望ましくない出力である 最後の オブジェクトのみが得られます。

以下の例では、最初の 5 つの実行中のプロセスを検索しています。それから PowerShell の Import-Csv foreach ループに入り、NameProductVersion のプロパティを一度に test.csv ファイルに記録しています。

Get-Process | Select-Object -First 5 | Foreach-Object {
    $_ | Select-Object Name, ProductVersion | Export-CSV -Path C:\test.csv -Append
}

Append パラメーターを使用しない場合、CSV ファイルには 5 番目のプロセスのみが表示されます。

CSV ファイルへの差分の追加

Export-Csv を使用して既存の CSV ファイルにプロパティの差分のみを追加することが可能です。つまり、CSV の行の列と記録するオブジェクトが異なる場合は、それらを追加します。

CSV ファイルに差分のみを追加するには、Append パラメーターと Force パラメーターを一緒に使用する必要があります。Microsoft のドキュメントによると、「Force パラメーターと Append パラメーターが組み合わされると、プロパティが一致しないオブジェクトも CSV ファイルに書き込むことができます。一致するプロパティのみがファイルに書き込まれ、一致しないプロパティは破棄されます」とのことです。

2つのプロパティ「Name」と「Age」を持つオブジェクトを作成します。

PS51> $Content = [PSCustomObject]@{Name = "Johnny"; Age = "18"}

次に、「Name」と「Zip」のプロパティを持つ別のオブジェクトを作成します。

PS51> $OtherContent = [PSCustomObject]@{Name = "Joe"; Zip = "02195"}

それぞれのオブジェクトは異なるプロパティを持ちます。

次に、最初のオブジェクトからCSVファイルを作成し、Forceパラメータを使用せずに2番目のオブジェクトをCSVに追加しようとすると、エラーが発生します。

PS51> $Content | Export-CSV -Path .\User.csv -NoTypeInformation
PS51> $OtherContent | Export-CSV -Path .\User.csv -NoTypeInformation -Append
Export-Csv without Force

ただし、Forceパラメータを使用すると、Export-Csvは正常に動作します。

PS51> $OtherContent | Export-CSV -Path .\User.csv -NoTypeInformation -Append -Force

ただし、CSVファイルでは「Zip」の列がないことに気付くでしょう。Forceは注意して使用してください。意図しない出力を提供する場合があります。

PS51> Import-Csv -Path .\User.csv

Name   Age
----   ---
Johnny 18
Joe

Export-CSV#TYPE文字列

デフォルトでは、追加のパラメータを指定せずにExport-CSVを使用すると、CSVファイルの先頭に#TYPE文字列が含まれます。この文字列は、Export-Csvが受け取ったオブジェクトのタイプに続きます。

#TYPE System.Diagnostics.Process

ほとんどの場合、この文字列は実際には出力を利用する際に役に立ちません。この文字列は、プロパティと値の元のオブジェクトのタイプを維持する必要がある場合にのみ存在します。

この文字列を削除するには、NoTypeInformationパラメータを使用します。このパラメータは、この文字列をCSVから完全に削除します。

PowerShell Coreでは、これはもはや必要ありません。

要約

Import-CSVExport-CSVのPowerShellコマンドレットを使用すると、CSVファイルを簡単に操作することができます。これらはオブジェクトとCSVファイルを扱う際に頻繁に使用すべき便利なコマンドレットです。

ここで表示した説明と例を通じて、これらのコマンドレットを活用できる状況を明確に理解していただければと思います。

このようなヒントをもっと知りたい場合は、私のパーソナルPowerShellブログをご覧ください。

Source:
https://adamtheautomator.com/import-csv/