使用awk进行操作:如果第n + 1行的$ 2中的值=第n行的$ 2中的value + 1,则从第n行打印$ 1,$ 2,从n和n + 1中平均得到$ 3

时间:2018-07-10 00:08:00

标签: unix awk

我试图找出一种比较长制表符分隔文件的第二列中值的方法。在每行的第二列中取一个值:如果下一行(在第二列中)的值比上一行大一个,那么我想对每行的第三列取平均值。例如:

ABC 111 9
ABC 114 4
ABC 115 5
ABC 117 5

并获得:

ABC 111 9
ABC 114 4.5
ABC 117 5

这远远超出了我的低级awk能力。 感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

对于您提供的示例,能否请您尝试遵循并让我知道这是否对您有帮助。

awk '
{
  if(($NF-prev)==1 && prev){
     print val1,val2,(prev+$NF)/2;
     val1=val2=prev="";
     next}
  else if(FNR>1 && prev){
     print val1,val2,prev}
}
{
  prev=$NF;
  val1=$1;
  val2=$2
}
END{
  if(FNR>1 && prev){
    print val1,val2,prev}
}'  Input_file

答案 1 :(得分:1)

假设您要合并并平均整个序列(其中后续行比上一行大一遍),以下代码段显示了一种方法:

count == 0 {                                # For start of first sequence.
    count=1;                                #   Set count for first sequence.
    last1=$1; first2=$2; last2=$2; sum=$3;  #   Store starting values.
    next                                    #   Go on to next line.
}
last2 + 1 == $2 {                           # Else for lines WITHIN sequence.
    count++;                                #   Increment count.
    last1=$1; first2=$2; last2=$2; sum+=$3; #   Adjust values.
    next                                    #   On to next line.
}
{                                           # Else this is a NEW sequence.
    print last1" "first2" "sum/count;       #   Print last sequence.
    count=1;                                #   Reset count for new sequence.
    last1=$1; first2=$2; last2=$2; sum=$3   #   Set starting values.
}
END {                                       # Handle final sequence here.
    if (count != 0) {                       #   Only if there were items.
        print last1" "first2" "sum/count
    }
}

使用该脚本,输入以下数据:

ABC 111 9
ABC 113 4
ABC 114 4
ABC 115 5
ABC 117 5

生成:

ABC 111 9
ABC 113 4.33333
ABC 117 5

它的工作方式是立即打印有关每一行的详细信息,而是存储该行的详细信息,直到评估下一行。

如果下一行是同一序列的一部分,则其详细信息将汇总为先前的详细信息,然后我们继续进行。

如果下一行是 new 序列的开始,那么我们输出前一个序列(当然,要进行汇总和平均),然后将下一行存储为序列的开始。 / p>

这意味着我们需要一个END块来处理最终序列,因为没有下一行会强制序列中断。


请注意,由于问题中未提及该字段,因此未将字段1更改考虑在内。为此,只需检测之前,然后检查“ this-field-2比last-field-2大一个”(上面的第二个块),然后继续执行新的顺序即可:

last1!=$1 {                                 # Changed field 1 is new sequence.
    print last1" "first2" "sum/count;       #   Print last sequence.
    count=1;                                #   Reset count for new sequence.
    last1=$1; first2=$2; last2=$2; sum=$3;  #   Set starting values.
    next                                    #   Get next line.
}