首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >按年计算的总和,并插入缺失项0

按年计算的总和,并插入缺失项0
EN

Stack Overflow用户
提问于 2019-03-22 14:08:07
回答 5查看 109关注 0票数 3

我有一份年度月报,如下所示

代码语言:javascript
运行
复制
201703 5
201708 10
201709 20
201710 40
201711 80
201712 100
201802 0
201803 25
201804 50
201805 50
201806 150
201807 300
201808 200
201902 10 

我需要总结每年的月份条目,并打印所有的月份后,为该特定的一年。年度月份可以有任何月份的缺失条目。对于这些月份,应该插入一个虚拟值(0)。

所需产出:

代码语言:javascript
运行
复制
201703 5
201704 0
201705 0
201706 0
201707 0
201708 10
201709 20
201710 40
201711 80
201712 100
2017 255
201801 0
201802 0
201803 25
201804 50
201805 50
201806 150
201807 300
201808 200
201809 0
201810 0
201811 0
201812 0
2018 775
201901 0
201902 10
201903 0
2019 10

我可以使用下面的命令获得年度摘要。

代码语言:javascript
运行
复制
awk ' { c=substr($1,0,4); if(c!=p) { print p,s ;s=0} s=s+$2 ; p=c ; print } ' ym.dat

但是,如何插入缺失的条目呢?最后一项不应超过当前(系统时间)年月.也就是说,对于这个特定的例子,不应该为201904..201905插入虚拟值。等等,只要用201903就行了。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2019-03-22 15:05:03

您可以使用此awk脚本mmyy.awk

代码语言:javascript
运行
复制
{
   rec[$1] = $2;
   yy=substr($1, 1, 4)
   mm=substr($1, 5, 2) + 0
   ys[yy] += $2
}

NR == 1 {
   fm = mm
   fy = yy
}

END {
   for (y=fy; y<=cy; y++)
      for (m=1; m<=12; m++) {
         # print previous years sums
         if (m == 1 && y-1 in ys)
            print y-1, ys[y-1]

         if (y == fy && m < fm)
            continue;
         else if (y == cy && m > cm)
            break;

         # print year month with values or 0 if entry is missing
         k = sprintf("%d%02d", y, m)
         printf "%d%02d %d\n", y, m, (k in rec ? rec[k] : 0)
      }
      print y-1, ys[y-1]
}

然后称之为:

代码语言:javascript
运行
复制
awk -v cy=$(date '+%Y') -v cm=$(date '+%m') -f mmyy.awk file

代码语言:javascript
运行
复制
201703 5
201704 0
201705 0
201706 0
201707 0
201708 10
201709 20
201710 40
201711 80
201712 100
2017 255
201801 0
201802 0
201803 25
201804 50
201805 50
201806 150
201807 300
201808 200
201809 0
201810 0
201811 0
201812 0
2018 775
201901 0
201902 10
201903 0
2019 10
票数 2
EN

Stack Overflow用户

发布于 2019-03-22 15:39:49

使用GNU awk作为strftime():

代码语言:javascript
运行
复制
$ cat tst.awk
NR==1 {
    begDate = $1
    endDate = strftime("%Y%m")
}
{
    val[$1] = $NF
    year = substr($1,1,4)
}
year != prevYear { prt(); prevYear=year }
END { prt() }

function prt(   mth, sum, date) {
    if (prevYear != "") {
        for (mth=1; mth<=12; mth++) {
            date = sprintf("%04d%02d", prevYear, mth)
            if ( (date >= begDate) && (date <=endDate) ) {
                print date, val[date]+0
                sum += val[date]
                delete val[date]
            }
        }
        print prevYear, sum+0
    }
}

代码语言:javascript
运行
复制
$ awk -f  tst.awk file
201703 5
201704 0
201705 0
201706 0
201707 0
201708 10
201709 20
201710 40
201711 80
201712 100
2017 255
201801 0
201802 0
201803 25
201804 50
201805 50
201806 150
201807 300
201808 200
201809 0
201810 0
201811 0
201812 0
2018 775
201901 0
201902 10
201903 0
2019 10

与其他awk一起,您只需使用endDate通过awk -v endDate=$(date +'%Y%m') '...'

票数 2
EN

Stack Overflow用户

发布于 2019-03-22 14:24:25

Perl来救我!

代码语言:javascript
运行
复制
perl -lane '$start ||= $F[0];
            $Y{substr $F[0], 0, 4} += $F[1];
            $YM{$F[0]} = $F[1];
            END { for $y (sort keys %Y) {
                      for $m (1 .. 12) {
                          $m = sprintf "%02d", $m;
                          next if "$y$m" lt $start;
                          print "$y$m ", $YM{$y . $m} || 0;
                          last if $y == 1900 + (localtime)[5]
                               && (localtime)[4] < $m;
                      }
                      print "$y ", $Y{$y} || 0;
                  }
              }' -- file
  • -n逐行读取输入
  • -l从输入中删除换行符并将它们添加到输出中。
  • -a将空格上的每一行拆分为@F数组
  • 底座从YYYYMM日期提取年份。散列%Y和%YM使用日期和键,计数为值。这就是为什么年份散列使用+=,它将值添加到已经累积的值中。
  • 结束块在输入耗尽后进行评估。
  • 它只重复存储在散列中的年份,范围为1 ..12用于月份以插入零( ||操作符打印它)。
  • 下一首$start跳过报告开始前的几个月。
  • 最后的负责跳过今年剩下的时间。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55301412

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档