CSVファイルを出力

前回は、テキストファイルを加工してCSVファイルを出力する例を紹介しました。元になるデータがPowerShellのオブジェクトであれば、Export-Csv(省略形epcsv)コマンドレットを使って簡単にCSVファイルを作成できます。

Export-Csvの書式は以下の通りです。

Export-Csv  保存ファイル名 -Encoding  文字コード

-Encodingオプションを省略したときASCIIコードで保存します。日本語を含むデータをShift JISコードで保存するには-Encoding default、Unicodeで保存するには、-Encoding unicodeオプションを使用してください。

gci | epcsv  test.csv  -Encoding default

Get-ChildItemの出力結果を、Export-CsvコマンドレットでCSVファイル化。

Export-Csvで保存したCSVファイルをExcel 2010で開いたところ。

CSVファイルを読み出す

一方、PowerShellでCSVファイルを加工するときに便利なコマンドレットImport-Csv(省略形ipcsv)があります。Import-CsvはCSVファイルを読み込み、PowerShellのオブジェクトに変換します。ただし、日本語を含むデータを処理するとき、CSVファイルの文字コードはUnicodeでなければなりません。

※稿末の囲み記事「日本語文字コードに注意」を参照してください。

Import-Csvで読み出したデータを、たとえば、Where-Objectを使って特定のレコードだけ抽出したり、ForEach-Objectで個々のレコードを加工したりできます。

ここでは、例として以下のCSVファイルを加工してみます。

CSVファイル address.csv。

※ 行頭に#のある行はImport-Csvではコメントとして無視します。ForEach-ObjectやWhere-Objectについては、当連載の第8回を参照して下さい。Import-Csvで読み出したCSVデータでは、CSVファイルの各レコード(行)が、ForEach-Objectの繰り返し単位になります。

まず、単純にImport-Csvで読み込んで表示すると、CSVファイルの内容を整形して表示します。

ipcsv  address.csv

Import-Csv(ipcsv)に読み出したaddress.csvのデータ。

Where-Object(省略形where)と組み合わせ、データの絞り込んでみます。

Import-Csvは、CSVファイルの1行目のレコードをフィールド名として認識しますので、例えば、営業2課のレコードを抽出するには、以下のように実行します。

ipcsv address.csv | where { $_.課 -like "営業2課" }

-like演算子は、文字列の適合を検証します。各レコードを$_変数で参照し、「$_.課 -like "営業2課"」で、「課」のフィールドを判定します。

「営業2課」のレコードだけを抽出。

-like演算子のの文字列判定にはワイルドカードも使用できますので、"営業*"(「営業」で始まる文字列)、"営業[12]課"(「営業1課」または「営業2課」)などのような指定も可能です。

ipcsv address | where { $_.ふりがな -like "さいとう*" }

「ふりがな」が「さいとう」で始まるレコードを抽出。

Import-Csvで読み出したデータについて、ForEach-Objectで、各レコードから「名前」フィールドと「メールアドレス」フィールドだけを抽出するには以下のようにします。

ipcsv address | foreach { $_.名前 + "," + $_.メールアドレス }

名前とメールアドレスだけを抽出。

出力の切り替え

さて、これまで、PowerShellではプログラム中の代入先がない変数や文字列は画面に表示すると説明しました。returnで指定した値も同様です。しかし、正確に言えば、これらはパイプラインへの出力です。パイプラインで次のフィルタに接続したりリダイレクトしたりしないときだけ、画面に表示します。パイプラインに出力するのではなく、何が何でも画面に表示するには、Write-Hostコマンドレットを使います。

たとえば、前述の名前とメールアドレスを出力するプログラムを、begin、process、endブロックを使ったスクリプトプログラム select-mailaddress.ps1 にして保存します。

※ begin、process、endブロックについては、当連載の第8回を参照して下さい。

スクリプトプログラム select-emailaddress.ps1

そのまま実行しただけでは、Write-Hostの違いがよくわかりませんが、出力をパイプラインで他のフィルタに接続したり、ファイルにリダイレクトするとWrite-Hostの違いがはっきりします。

リダイレクト先がなければ、Write-Hostも他の出力も一緒に画面に表示。

select-emailaddress.ps1の出力をリダイレクトすると、パイプラインに出力されたデータは表示されず、Write-Hostによる出力だけを表示します。

パイプラインの出力はテキストファイル mailaddress.csv に保存。Write-Hostによる表示はあくまで画面に表示。

こうした出力の使い分けは、スクリプトや関数実行の時のメッセージ表示や、プログラミングのデバグ(バグ修正)時の処理データの表示などに利用できます。たとえば、プログラムが思い通りに動かないとき、プログラム中にWrite-Hostで処理中のデータを表示する行を挿入すれば、プログラムの動作状況がわかって不具合の原因究明に役立ちます。

※ 他にも異なる出力コマンドレットがあります。「help Write-*」で参照してみて下さい。

日本語文字コードに注意

Import-Csvで日本語データを含むCSVファイルを読み込んで処理するとき、UnicodeのCSVファイルでなければ、日本語文字が文字化けして正常にオブジェクト化できません。CSVファイルの元データがShift JISコードであれば、以下のようにリダイレクトすることで簡単にUnicodeに変換して保存できますので、Unicodeに変換してから利用して下さい。

 Get-Content Shift-JISコードのファイル名 > Unicodeのファイル名

現在のPC環境では、伝統的なShift JISコードと急速に普及してきたUnicodeが混在使用されています。たとえば、日本語を含むCSVファイルを読み込むとき、ExcelならShift JISコードのテキストファイルを読み込みますが、Import-CsvコマンドレットではUnicodeのCSVファイルを必要とします。PowerShellではUnicodeを基本としていますが、Shift JISコードも使わざるを得ないことも多く、やや混乱気味です。

日本語テキストファイルを処理するときは、どの文字コードで入出力しているのか、常に気を配る必要があります。