定例的なテキスト整形やデータ集計なんかは、コマンド操作でやっつけてしまいたいですよね。今回は、Powershell で CSVファイルに列(カラム)を追加する方法を紹介します。
PowershellでCSVに列・カラムを追加する
まずは、編集前の元データを確認します。以下は、単純にcatで表示させた状態。
1 2 3 4 |
> cat .\before.csv yamada,33,infra,Leader suzuki,28,dev,Chief tanaka,46,sales,Manager |
このデータに対して、2列目(B列)を追加したいという状況です。
以下のスクリプトで実現可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
### 設置パス/スクリプトファイル名取得 $baseDir = Split-Path $myInvocation.MyCommand.path ### 入力/出力ファイルパス定義 $impCsvFile = "$baseDir\before.csv" $expCsvFile = "$baseDir\after.csv" ### B列を追加 # 元データ(CSV)読み込み ※ヘッダを付与する:columnA,columnB,columnC,columnD $target = Import-Csv $impCsvFile -Header columnA,columnB,columnC,columnD -Encoding UTF8 $target | ForEach-Object { # 各カラムを変数に格納 $column_A = $_.columnA $column_B = $_.columnB $column_C = $_.columnC $column_D = $_.columnD # A列の行末にカンマを付与(B列を追加) $column_A = $column_A -replace "$" , "," # B列を追加した状態でCSVファイルに出力 Write-Output "$column_A,$column_B,$column_C,$column_D" | out-file $expCsvFile -Encoding UTF8 -Append } |
主なポイントとしては、以下の3点かと。
- データをCSVとして読み込む際に、ヘッダを付与する
- 各カラムをForeach-Objectで行ごとに変数に格納していく
- 列の追加は追加したいカラムの行末に「,(カンマ)」を追加する(行末をカンマに置換)
- CSVに出力する際は、Export-csv でなく、out-file で出力する
今回は「B列を追加する」という要件でしたので、A列の行末にカンマを付与しました。追加する箇所によって、カンマを付与する列を調整してください。カンマを付与したら、再度、ファイルにエクスポートすることで、結果的に列・カラムが増える、という仕様です。
以下が実行後のデータをcatで表示したものです。2列目が追加されていますね。
1 2 3 4 |
> cat .\after.csv yamada,,33,infra,Leader suzuki,,28,dev,Chief tanaka,,46,sales,Manager |
追加した列・カラムにデータを追加する
↑で列・カラムを追加しましたが、B列にはデータがない空っぽの状態です。この列にデータを追加していきます。
まずは、ファイルの内容の確認です。(↑のファイル名を after.csv → before.csv に変更しました。)
1 2 3 4 5 |
> mv .\after.csv .\before.csv > cat .\before.csv yamada,,33,infra,Leader suzuki,,28,dev,Chief tanaka,,46,sales,Manager |
では、このデータの2列目に、今回は例として 時刻 を追加していきます。
以下のスクリプトで実行します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
### 設置パス/スクリプトファイル名取得 $baseDir = Split-Path $myInvocation.MyCommand.path ### 入力/出力ファイルパス定義 $impCsvFile = "$baseDir\before.csv" $expCsvFile = "$baseDir\after.csv" # 先の処理で書き出したCSVファイルを読み込み ※1列追加したので、A~E列までのヘッダを指定 $target = Import-Csv $impCsvFile -Header columnA,columnB,columnC,columnD,columnE -Encoding UTF8 $target | ForEach-Object { # 各カラムを変数に格納 $column_A = $_.columnA $column_B = $_.columnB $column_C = $_.columnC $column_D = $_.columnD $column_E = $_.columnE # B列に日時を追加する $column_B = Get-Date -Format "yyyy/MM/dd HH:mm:ss " # A~E列までをCSV出力 Write-Output "$column_A,$column_B,$column_C,$column_D,$column_E" | out-file $expCsvFile -Encoding UTF8 -Append sleep 1 } |
主なポイントとしては、
- CSVを読み込む際に付与するヘッダは、1列追加したことから、1列分増やすこと(A~D → A~E )
- 変数に格納する際もA~Eまでとする(1列増やす)※エクスポートする際も同じ
基本的には、Foreach-Object で行ごとに処理をしていくことは、先程のスクリプトと同じです。スクリプト内のコメントの「B列に日時を追加する」の箇所に、追加したいデータを算出する処理を入れればOKです。sleep をいれているのは、行ごとに時刻が違ったほうがわかりやすいかと思っただけなので深い意味はないです。
そして、以下が実行後のデータをcatで表示したものです。
1 2 3 4 |
> cat .\after.csv yamada,2020/02/09 21:02:33,33,infra,Leader suzuki,2020/02/09 21:02:34,28,dev,Chief tanaka,2020/02/09 21:02:35,46,sales,Manager |
まとめ
いかがでしたでしょうか。
少し力技な感じも否めませんが、これで Powershell で CSV に列の追加ができるようになります。例えば、Linuxでは、awk で同じようなことができますね。awkでのやり方は以下のページで紹介しています。
では。
-
awk コマンド の使い方
awk や sed を使ってテキスト整形するときにいつも使い方を忘れるので、メモします。このエントリはawkです。 awk コマンド の使い方 記載内容は独断と偏見で偏ってます。さらに場合によっては、 ...