检测任何列中的增量

时间:2018-01-22 10:23:42

标签: bash awk

我有以下数据作为输入。我试图找到每组的增量。

tango: 300
charlie:0
beta:100
alpha:0

示例输出:

awk 'NR>1{print $NF}' foo |while read line;do grep -w $line foo|sort -k3n ;done |awk '!a[$4]++' |sort -k4
1       2       100     alpha
3       4       200     beta
5       6       700     charlie
7       8       300     tango
awk 'NR>1{print $NF}' foo |while read line;do grep -w $line foo|sort -k3n ;done |tac|awk '!a[$4]++' |sort -k4
1       2       100     alpha
3       4       300     beta
5       6       700     charlie
7       8       700     tango

我正在尝试这个approch,但答案是不正确的,因为样本之间的值有时会增加:

selectedDay

4 个答案:

答案 0 :(得分:3)

Awk 解决方案:

awk 'NR==1{ next }
     g && $4 != g{ print g":"(v - gr[g]) }
     !($4 in gr){ gr[$4]=$3 }{ g=$4; v=$3 }
     END{ print g":"(v - gr[g]) }' file
  • NR==1{ next } - 跳过第一条记录
  • g - 旨在保存群组名称
  • 的变量
  • v - 旨在保存群组值的变量
  • !($4 in gr){ gr[$4]=$3 } - 在第一次出现不同的群组名称$4时 - 将其第一个值$3保存到数组gr
  • g && $4 != g{ print g":"(v - gr[g]) } - 如果当前组名称$4与前一个组g不同 - 在前一组的最后一个值和第一个值之间打印 delta

输出:

alpha:0
beta:100
charlie:0
tango:300

答案 1 :(得分:2)

以下应该可以解决问题,此解决方案不要求按组名对文件进行排序。

awk '(NR==1){next}
     {groupc[$4]++}
     (groupc[$4]==1){groupv[$4]=$3}
     {groupl[$4]=$3}
     END{for(i in groupc) { print i":",groupl[i]-groupv[i]} }
    ' foo

发生以下情况:

  • 跳过第一行(NR==1){next}
  • 计算发生的时间组{groupc[$4]++}
  • 如果组计数等于1,则在groupv
  • 下定义其第一个值
  • 将上次看到的值定义为groupl
  • 在END处,遍历所有数组键(即组),并打印最后一个减去第一个值。

输出:

tango: 300
alpha: 0
beta: 100
charlie: 0

答案 2 :(得分:1)

关注awk也可能对您有帮助。它将按照Input_file的最后一列值以相同的顺序提供输出。

awk '
FNR==1{
  next}
prev!=$NF && prev{
  val=prev_val!=a[prev]?prev_val-a[prev]:0;
  printf("%s %d\n",prev,val>0?val:0)}
!a[$NF]{
  a[$NF]=$(NF-1)}
{
  prev=$NF;
  prev_val=$(NF-1)}
END{
  val=prev_val!=a[prev]?prev_val-a[prev]:0;
  printf("%s %d\n",prev,val>0?val:0)}
'   Input_file

输出如下。将很快添加解释。

alpha 0
beta 100
charlie 0
tango 300

说明: 现在为了学习目的而添加代码说明。

awk '
FNR==1{                                    ##To skip first line of Input_file which is heading I am putting condition if FNR==1 then do next, where next will skip all further statements of awk.
  next}
prev!=$NF && prev{                         ##Checking conditions here if variable prev value is NOT equal to current line $NF and variable prev is NOT NULL then do following:
  val=prev_val!=a[prev]?prev_val-a[prev]:0;##create a variable val, if prev_val is not equal to a[prev] then subttract prev_val and s[prev] else it will be zero.
  printf("%s %d\n",prev,val>0?val:0)}      ##printing the value of variable prev(which is nothing but value of last column) and then print value of val if greater than 0 or print 0 in place of val here.
!a[$NF]{                                   ##Checking if array a value whose index is $NF is NULL then fill it with current $NF value, actually this is to get the very first value of any column so that later we could subtract it with the its last value as per OP request.
  a[$NF]=$(NF-1)}
{
  prev=$NF;                                ##creating variable named prev and assigning its value to last column of the current line.
  prev_val=$(NF-1)}                        ##creating variable named prev_val whose value will be second last columns value of current line.
END{                                       ##starting end block of awk code here, it will come when Input_file is done with reading.
  val=prev_val!=a[prev]?prev_val-a[prev]:0;##getting value of variable val where checking if prev_val is not equal to a[prev] then subtract prev_val and s[prev] else it will be zero.
  printf("%s %d\n",prev,val>0?val:0)}      ##printing the value of variable prev(which is nothing but value of last column) and then print value of val if greater than 0 or print 0 in place of val here.
' Input_file                               ##Mentioning the Input_file name here.

答案 3 :(得分:0)

$ cat tst.awk
NR==1 { next }
!($4 in beg) { beg[$4] = $3 }
{ end[$4] = $3 }
END {
    for (grp in beg) {
        print grp, end[grp] - beg[grp]
    }
}

$ awk -f tst.awk file
tango 300
alpha 0
beta 100
charlie 0