【问题标题】:Summing Columns Between Timestamp/Newline Delimiters Using Bash Script使用 Bash 脚本对时间戳/换行符分隔符之间的列求和
【发布时间】:2015-10-20 19:01:36
【问题描述】:

我有以下形式的数据:

23:31:39
20 0 24436 404 56 R 2.7 0.0 1:38.52
20 0 43064 20112 4484 R 0.8 0.1 0:00.12
20 0 27116 5152 3856 S 0.3 0.0 0:00.05
20 0 24952 4672 3708 S 0.0 0.0 0:00.05
23:31:54
20 0 24436 404 56 R 2.7 0.0 1:38.93
20 0 24952 4672 3708 S 0.0 0.0 0:00.05
23:32:09
20 0 24436 404 56 R 2.6 0.0 1:39.32
20 0 24952 4672 3708 S 0.0 0.0 0:00.05
23:32:24
20 0 24436 404 56 R 2.9 0.0 1:39.76
20 0 24952 4672 3708 S 0.0 0.0 0:00.05

上面的数据交替使用黑白时间戳行,然后是要求和的数据行。

我想对每个时间戳下的行中的列求和,这样当我添加 say...column 1 时,我得到的结果如下所示:

23:31:39
80
23:31:54
40
23:32:09
40
23:32:24
40

当我添加第 1 列和第 7 列时,我得到:

23:31:39
80 3.8
23:31:54
40 2.7
23:32:09
40 2.6
23:32:24
40 2.9

我将如何以这种方式处理数据?我正在尝试将它变成一种我可以轻松绘制的形式。

【问题讨论】:

    标签: linux bash parsing awk sed


    【解决方案1】:

    另一个 awk

    $ awk ' NF==1 { if(NR>1) print p,t1,t7 ;p=$0 ; t1=t7=0 } NF!=1 { t1+=$1;t7+=$7 } END { print p,t1,t7 }  ' mnot.txt
    23:31:39 80 3.8
    23:31:54 40 2.7
    23:32:09 40 2.6
    23:32:24 40 2.9
    $
    

    【讨论】:

      【解决方案2】:

      这是@rici 答案的perl 替代方案。请注意,数组索引从 0 开始,因此这个数据示例使用第 0 列和第 6 列而不是第 1 列和第 7 列。

      #!/usr/bin/perl
      
      use strict;
      
      my @wanted_cols = (0,6);
      
      my %sums;
      
      while (<>) {
          my @cols = split /\s+/;
          if ($#cols) {
              foreach my $w (@wanted_cols) { $sums{$w} += $cols[$w] }
          } else {
              print join("\t", @sums{ @wanted_cols }), "\n";
              %sums = ();
              print $_;
          }
      }
      print join("\t", @sums{ @wanted_cols }), "\n";
      

      【讨论】:

        【解决方案3】:

        这是一个 awk 解决方案,您可能可以根据自己的需要进行调整。

        它实际上为每个时间戳/聚合生成一行,因为这通常更容易绘制。但是更改输出格式会很容易。

        # file: aggregate.awk
        #
        # Call this as follows:
        # awk -v columns=1,7 -f aggregate.awk data.file
        BEGIN {
            ncols = split(columns, cols, /,/);
        }
        function print_line() {
            if (ts != "") {
                printf "%s", ts;
                for (i = 1; i <= ncols; ++i) printf " %f", data[i];
                printf "\n";
            }
        }
        
        /^..:..:../ {
            print_line();
            ts = $0;
            for (i = 1; i <= ncols; ++i) data[i] = 0;
            next;
        }
            { for (i = 1; i <= ncols; ++i) data[i] += $(cols[i]); }
        END { print_line(); }
        

        例子:

        $ awk -v columns=1,7 -f aggregate.awk <<EOF
        23:31:39
        20 0 24436 404 56 R 2.7 0.0 1:38.52
        20 0 43064 20112 4484 R 0.8 0.1 0:00.12
        20 0 27116 5152 3856 S 0.3 0.0 0:00.05
        20 0 24952 4672 3708 S 0.0 0.0 0:00.05
        23:31:54
        20 0 24436 404 56 R 2.7 0.0 1:38.93
        20 0 24952 4672 3708 S 0.0 0.0 0:00.05
        23:32:09
        20 0 24436 404 56 R 2.6 0.0 1:39.32
        20 0 24952 4672 3708 S 0.0 0.0 0:00.05
        23:32:24
        20 0 24436 404 56 R 2.9 0.0 1:39.76
        20 0 24952 4672 3708 S 0.0 0.0 0:00.05
        EOF
        
        23:31:39 80 3.8
        23:31:54 40 2.7
        23:32:09 40 2.6
        23:32:24 40 2.9
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-03-07
          • 1970-01-01
          • 2020-10-30
          • 1970-01-01
          • 1970-01-01
          • 2012-01-06
          • 1970-01-01
          相关资源
          最近更新 更多