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