我有一百个CSV文件,每个文件有200k行,压缩为gzip 所有文件具有相同的结构。第15和第18列包含companyID和action 两列都是独一无二的。 我想为每个copanyID.action创建一个文件。 现在我运行这个命令:
zcat * | grep 'companyID.*action' | gzip > companyID.action.gz
我管道所有内容以避免磁盘IO。
问题是我们有数百家公司和大约20项行动。 在每个companyID X操作上运行此命令每次都会扫描整个数据。
我正在寻找一种扫描输入文件的解决方案,并在右侧文件中写一行,如果文件不存在则创建一个。
我更喜欢bash或Golang代码,但速度很重要所以每个解决方案都值得检查
答案 0 :(得分:1)
使用awk
。
scat * | awk '{ print | "gzip > " $15 "." $18 ".gzip" }'
答案 1 :(得分:1)
这应该这样做:
zcat * |
awk -F, '{cmd="gzip >> \""$15"."$18".zip\""} cmd!=prev{close(prev)} {print | cmd; prev=cmd}'
使用GNU awk,您不需要cmd!=prev{close(prev)}
部分,如果您这样做:
zcat * |
sort -t, -k15,15 -k18,18 |
awk -F, '{cmd="gzip > \""$15"."$18".zip\""} cmd!=prev{close(prev)} {print | cmd; prev=cmd}'
它可能会运行得更快,因为它只会在awk命令中打开/关闭每个输出管道一次,只取决于sort
需要多长时间。
答案 2 :(得分:0)
我不知道scat
做了什么。我用zcat
代替了。我按相关列对所有文件的所有行进行了排序,然后在Perl中处理输出,当相关列中的值发生更改时更改输出文件:
zcat *.csv.gz \
| sort -t, -k15,15 -k18,18 \
| perl -laF, -ne '
if ($company ne $F[14] || $action ne $F[17]) {
($company, $action) = @F[14, 17];
open FH, ">", "$company.$action.csv"
}
print FH $_'
gzip *.*.csv