Help us understand the problem. What is going on with this article?

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

More than 5 years have passed since last update.

あるファイルがあり、以下のような中身だったとします。
これの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で区切るやり方が簡単かと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした