AWK - 匹配后对特定字段求和

时间:2017-04-30 23:29:07

标签: awk

我有一个长度为10到数百行的txt文件,如果前一个字段匹配,我需要将每一行(和输出)的特定字段相加。

以下是一个示例数据集:

Sample4;6a0f64d2;size=1;,Sample4;f1cb4733a;size=6;,Sample3;aa44410feb29210c1156;size=2;
Sample2;5b91bef2329bd87f4c7;size=2;,Sample1;909cd4e2940f328b3;size=2;

结构是

<sample ID>;<random id>;size=<numeric>;,然后是下一个条目。一行中可能有数百个条目(这只是一个小例子)

基本上,我想总结一行中每个条目的“大小”数字(由','分隔的条目),但只有那些与特定样本标识符匹配的条目(例如,例如sample4)
因此,如果我们只想匹配'Sample4',那么脚本会产生这个 -

awk '{some-code for sample4}' example.txt
7
0

因为带有'Sample4'的条目在第1行中加起来为7,但在第2行中,没有Sample4条目匹配。

这可以针对每个“SampleID”进行,或者理想情况下,对列表中提供的所有样本ID(可能在简单文件中,每个样本ID 1行)完成,然后输出每行的计数,每个样品ID有自己的列 - 例如对于上面的示例文件,脚本的结果将是:

Sample1  Sample2  Sample3  Sample4
0        0        2        7  
2        2        0        0

有关如何入门的任何想法?

谢谢!

2 个答案:

答案 0 :(得分:2)

另一个awk

 awk -F';' '{for(i=1;i<NF-1;i+=3) 
               {split($(i+2),e,"="); 
                sub(/,/,"",$i); 
                header[$i]; 
                a[$i,NR]+=e[2]}} 
        END {for(h in header) printf "%s", h OFS; 
             print "";
             for(i=1;i<=NR;i++) 
               {for(h in header) printf "%s", a[h,i]+0 OFS;
                print ""}}' file | column -t


Sample1  Sample2  Sample3  Sample4
0        0        2        7
2        2        0        0

PS。列的顺序无法保证。

<强>解释 为了简化解析,我使用;作为分隔符,并在名称之前删除了,。使用结构使用多维数组a为每行指定名称=值的总和,分别跟踪标题数组中的所有名称。一旦消耗了行,在END块中打印标题,并为每一行打印相应名称的值(如果缺少则为0)。使用column -t精美打印。

答案 1 :(得分:0)

如果我理解正确,你可以这样做:

$ awk '{split($0,samp,/,/)
      for (i=1; i in samp; i++){
        sub(/;$/, "", samp[i])
        split(samp[i], fields, /;/)
        split(fields[3], ns, /=/)
        data[fields[1]]+=ns[2]
     }
      printf "For line %s:\n", NR
      for (e in data)
           print e, data[e]
      split("", data)  
 }' file

打印:

For line 1:
Sample3 2
Sample4 7
For line 2:
Sample1 2
Sample2 2