grep到多个文件,以便扫描输入文件一次

时间:2016-06-04 07:26:22

标签: bash csv grep

我有一百个CSV文件,每个文件有200k行,压缩为gzip 所有文件具有相同的结构。第15和第18列包含companyID和action 两列都是独一无二的。 我想为每个copanyID.action创建一个文件。 现在我运行这个命令:

zcat * | grep 'companyID.*action' | gzip > companyID.action.gz

我管道所有内容以避免磁盘IO。

问题是我们有数百家公司和大约20项行动。 在每个companyID X操作上运行此命令每次都会扫描整个数据。

我正在寻找一种扫描输入文件的解决方案,并在右侧文件中写一行,如果文件不存在则创建一个。

我更喜欢bash或Golang代码,但速度很重要所以每个解决方案都值得检查

3 个答案:

答案 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