前 3 行

前 3 行

我有 2 个文件,第一个是一个记录文件,它告诉我对第二个文件中的哪些行感兴趣(我将其称为 FILTER_FILE)。该文件可以包含重复的行,我只需要为第一个文件中的每个唯一行处理第二个文件。
第二个文件(我们称之为 DATA_FILE)包含文件 1 中每一行的多行,并且有一个数字需要对第一个文件中每个匹配项的前 3 次出现进行求和(其他文件可以被丢弃)。

我已经尝试了一些东西,但我的知识awk是基础的,尽管我正在尽可能多地使用它来尝试拿起它。

这是我尝试过的相当笨拙的尝试:

awk '{print $1 " " $2}' filter_file | sort -u >> tst

while read filter; 
    do grep "$filter" data_file | head -3; done < tst >> ./short_data_file

while read line;
    do grep "$filter" short_data_file | awk '{ sum += $3 } END { print $1 " " $2 " " sum }' ; done < tst >> summary_file

过滤器文件示例格式:

abcd 123456  
abcd 123456  
abcd 123456  
abcd 123457  
abcd 234567  
abcd 234567  
abcd 234567  
abcd 890123  
abcd 890123  
abcd 890123  
abcd 890123  
abcd 890123  
abde 344566  
abde 344566  
abde 344566 

数据文件示例格式:

abcd 123456 3  
abcd 123456 4  
abcd 123456 3  
abcd 123456 56  
abcd 123456 6   
abcd 123456 1   
abcd 123457 6  
abcd 123457 4  
abcd 123457 89  
abcd 123457 3  
abcd 123457 9  
abcd 234567 5  
abcd 234567 3  
abcd 234567 8   
abcd 234567 6  
abcd 234567 76  
abcd 234567 34  
abcd 234567 0  
abcd 234567 7  
abcd 890123 5  
abde 344566 152  

编辑:这是由上述数据文件生成的输出

abcd 123456 10  
abcd 123457 99  
abcd 234567 16  
abcd 890123 5  
abde 344566 152   

编辑:实际的真实数据文件会很大;过滤器文件中有数千个,数据中有数百万个。

答案1

尝试

awk 'NR == FNR { data[$1 " " $2]=0 ; next ; }
{ if ($1 " " $2 in data) data[$1 " " $2]+=$3 }
 END { for ( d in data ) printf "%s %d\n",d,data[d] ;} ' filter data

(这可以在一行中)

在哪里

  • NR == FNR { data[$1 " " $2]=0 ; next ; }存储过滤器文件中的行
  • { if ($1 " " $2 in data) data[$1 " " $2]+=$3 }如果在数据中,则从第三列添加值
    • END { for ( d in data ) printf "%s %d\n",d,data[d] ;}打印总和

请注意,输出顺序是随机的,您可能希望通过管道传输到sort.

前 3 行

这是修改后的 awk

NR == FNR { countit[$1 " " $2]=0 ; next ; }
{ if ($1 " " $2 in countit) {
    data[$1 " " $2]+=$3 ;
    countit[$1 " " $2] ++ ;
    if ( countit[$1 " " $2] == 3 ) {
            printf "%s %s %s\n",$1,$2,data[$1 " " $2] ;
            delete data[$1 " " $2] ;
            delete countit[$1 " " $2] ;
    }
    }
}

 END { for ( d in data ) printf "%s %d\n",d,data[d] ;}

根据如何处理不完整列表(例如 1 或 2 个元素),您可以删除 END 行。

相关内容