使用 awk 与前一个索引相减,其中索引不是数字

使用 awk 与前一个索引相减,其中索引不是数字

我想从以前的值中减去值,但必须满足一个条件。

文件:

2022-02-01 01:00:00|abc|2001|5
2022-02-01 01:00:00|abc|2002|10
2022-02-01 01:01:00|abc|2001|6
2022-02-01 01:01:00|abc|2002|11
2022-02-01 01:02:00|abc|2001|10
2022-02-01 01:02:00|abc|2002|11
2022-02-01 01:02:00|abc|2003|2

期望的输出:

2022-02-01 01:00:00|abc|2001|5
2022-02-01 01:00:00|abc|2002|10
2022-02-01 01:01:00|abc|2001|1
2022-02-01 01:01:00|abc|2002|1
2022-02-01 01:02:00|abc|2001|4
2022-02-01 01:02:00|abc|2002|0
2022-02-01 01:02:00|abc|2003|2

我尝试使用 awk 但无法到达前一个索引来减去该值

awk -F"|" 'BEGIN{OFS="|"}{a[$1,$2,$3]=$4}END{for (i in a) print i, a[i]-a[i-1] }' file

答案1

看来你想做的是这样的:

awk -v FS="|" -v OFS="|" '{ a=$4;if($3 in dict)$4-=dict[$3]; dict[$3]=a}1' file

associative arrays在 awk 中使用来存储您拥有的年份作为键,它们的值将是最后一列。例如,该数组应如下所示:

dict[2001] = "4th column"
dict[2002] = "4th column"
dict[2003] = "4th column"
....

所以dict 键/值是这样的:

dict[2001] = "5"
dict[2002] = "10"
dict[2001] = "6"
dict[2002] = "11"
dict[2001] = "10"
dict[2002] = "11"
dict[2003] = "2" # this never changes because you have only one 2003 as year.

因此,使用 awk 代码:a=$4;if($3 in dict)$4-=dict[$3]; dict[$3]=a我可以dict根据当前关键年份减去第四列中存储的最后一个值。3 美元是年份$4 是索引/值


正如您在评论中所说,keys关联数组似乎应该是abc|year。如果是这样,那么你应该使用这个:

awk -F'|' -v OFS='|' '{a=$4; if(($2,$3) in dict)$4-=dict[$2,$3]; dict[$2,$3]=a }1' file

答案2

使用miller

mlr --nidx --fs '|' put '$delta = is_present(@last[$3]) ? $4 - @last[$3]  : $4; @last[$3] = $4; unset $4' file

在此命令中,第四个字段存储在@last第三个字段的索引中。is_present查看是否@last[$3]为真(即当前记录的第三个字段上存在索引变量),然后打印两个值之间的差异。否则它打印第四个字段。

最后第四个字段未设置。

如果不需要第一个值,则可以使用以下值。

 mlr --nidx --fs '|' step -g 3 -a delta -f 4 file

相关内容