11
12

More than 5 years have passed since last update.

powershellでCSV等の区切り文字があるファイルの数値列の合計を計算する

Posted at

あるファイルがあり、以下のような中身だったとします。
これの3列目の数値の合計を計算する方法を考えます。

aaaa,bbbb,200,cccc
dddd,eeee,300,ffff
gggg,hhhh,400,iiii
jjjj,kkkk,500,llll

linuxの場合は、awkを使って以下のように計算できます。

# cat test1a.txt | awk -F, '{sum += $3} END {print sum}'
1400

powershellの場合は以下で3列目の合計が計算できます。


Get-Content .\test3.txt | %{$sum += [int]$_.split(",")[2]};$sum

もしくは

Import-Csv .\test3.txt -header(1..4) | Select-Object "3" | %{$sum += [int]$_.3};$sum

パターン1の解説
%はforeachのエイリアスです。
foreach中は$_に一行づつ代入されます。
まず各行は,で区切られているので、splitで分割します。
分割した行は配列として扱われます。
配列でいうとカンマ区切りの3列目はインデックス[2]です。
$sum$_を加算していき、最後に$sumを表示します。
$_はそのままだと文字列として扱われるため、[int]でキャストしています。
区切り文字がカンマ以外の場合は、splitでその区切り文字を指定すればすぐに応用できます。

コマンドライン上で計算する場合は、このパターン1のほうが覚えやすいと思います。

パターン2の解説
Import-CSVコマンドレットを使います。
このコマンドレットはCSV扱うためのものです。
デフォルトだと先頭行が列名として扱われてしまうため、-headerオプションで列名を作成しています。
select-object以降を消して実行すると以下の結果になります。
列ごとにオブジェクト化されるようです。


PS E:\work> Import-Csv .\test3.txt -header(1..4)

1                             2                             3                             4
-                             -                             -                             -
aaaa                          bbbb                          200                           cccc
dddd                          eeee                          300                           ffff
gggg                          hhhh                          400                           iiii
jjjj                          kkkk                          500                           llll

Select-Objectで列名3を取得しています。

$_.3で計算しているのは、以下のためです。

%{$_ | GetMember}の結果

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
3           NoteProperty System.String 3=200

$_.Get-Tyep()の結果


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

つまり$_のままだとPSCustomObjectとして扱われるため、この中のプロパティである3に
実際の数値がString型で格納されているため参照しているわけです。

パターン2で使用するimport-csvはすべてのカラムをオブジェクトに入れてくれるので
powershellスクリプトなどで、どのカラムも計算対象・処理対象になる等の場合に使用する場合は便利だと思います。
コマンドライン上である列の値の合計だけ出したいときはパターン1の単純にsplitで区切るやり方が簡単かと思います。

11
12
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
12