我有一个csv文件,其中包含有关我要转换的单独行上的客户端的数据。
当前布局是:
Client_Name,Client_ID,Client_Group,Attribute_Name,Date,Attribute_Value
每行包含有关客户端的信息,例如:
Acme,0001,Marketing,Sales_Amt,2010-10-01,100
Acme,0001,Marketing,Queries,2010-10-01,3
Smiths,0002,Retail,Sales_Amt,2010-10-01,1200
Smiths,0002,Retail,Queries,2010-10-01,11
我要做的是将其转换为以下时间序列布局:
Date,Client_Name,Sales_Amt,Queries
以便每一行都显示为:
2010-10-01,Acme,100,3
2010-10-01,Smiths,1200,11
所以我可以每天查看每个客户属性。这是ETL的工作,还是仅使用sed和awk之类的文件处理工具就可以轻松地做到这一点?
Perl及其Text::CSV_XS进行救援!
perl -MText::CSV_XS=csv -we '
csv(in => shift,
on_in => sub { $h{ $_[1][4] }{ $_[1][0] }[ $_[1][3] eq "Queries" ] = $_[1][5] },
out => \"skip");
csv(in => [ map { $x = $_;
map [$x, $_, @{ $h{$x}{$_} } ],
sort keys %{ $h{$_} }
} sort keys %h ]);
' -- file.csv
它首先用您要保留的数据填充哈希%h
,然后将其输出为新的csv。
$ cat tst.awk
BEGIN { FS=OFS="," }
{
sub(/\r$/,"")
curr = $5 OFS $1
}
curr != prev {
if ( NR > 1 ) {
print prev, vals[1], vals[2]
}
prev = curr
cnt = 0
}
{ vals[++cnt] = $NF }
END {
print prev, vals[1], vals[2]
}
$ awk -f tst.awk file
2010-10-01,Acme,100,3
2010-10-01,Smiths,1200,11
有关使用awk解析CSV的更多信息,请参见What's the most robust way to efficiently parse CSV using awk?。>