あるファイルがあり、以下のような中身だったとします。
これの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で区切るやり方が簡単かと思います。
追記(6/21)
サクラエディタの正規表現を用いた方法も考えました。
monaski.hatenablog.com