【问题标题】:AWK file reformattingAWK 文件重新格式化
【发布时间】:2016-06-02 10:56:17
【问题描述】:

我正在努力使用 awk 重新格式化逗号分隔的文件。该文件包含多台服务器和多个指标一天的分钟数据
例如 2 条记录,每分钟,每台服务器 24 小时

示例输入文件:

server01,00:01:00,AckDelayAverage,9999  
server01,00:01:00,AckDelayMax,8888  
server01,00:02:00,AckDelayAverage,666  
server01,00:02:00,AckDelayMax,5555  
.....  
server01,23:58:00,AckDelayAverage,4545  
server01,23:58:00,AckDelayMax,8777  
server01,23:59:00,AckDelayAverage,4686  
server01,23:59:00,AckDelayMax,7820  
server02,00:01:00,AckDelayAverage,1231  
server02,00:01:00,AckDelayMax,4185  
server02,00:02:00,AckDelayAverage,1843  
server02,00:02:00,AckDelayMax,9982  
.....  
server02,23:58:00,AckDelayAverage,1022  
server02,23:58:00,AckDelayMax,1772  
server02,23:59:00,AckDelayAverage,1813  
server02,23:59:00,AckDelayMax,9891  

我正在尝试重新格式化文件,使其每分钟有一行,并将字段 1 和 3 的唯一串联作为列标题

例如,预期的输出文件如下所示:

Minute, server01-AckDelayAverage,server01-AckDelayMax, server02-AckDelayAverage,server02-AckDelayMax  

00:01:00,9999,8888,1231,4185  
00:02:00,666,5555,1843,8892  
...  
...  
23:58:00,4545,8777,1022,1772  
23:59:00,4686,7820,1813,9891  

【问题讨论】:

  • 您可以尝试使用join 命令进行数据分组。否则,以时间戳字符串为键的awk 中的关联数组。
  • 糟糕,您忘记发布代码了! StackOverflow 旨在帮助人们修复他们的代码。这不是免费的编码服务。任何代码都比没有代码好。元代码甚至可以展示您认为程序应该如何工作,即使您不知道如何编写它。

标签: linux shell awk scripting


【解决方案1】:

使用 GNU awk 的解决方案。将此称为awk -F, -f script input_file

/Average/ { average[$2, $1] = $4; }
/Max/ { maximum[$2, $1] = $4; }
{
    if (!($2 in minutes)) {
        minutes[$2] = 1;
    }
    if (!($1 in servers)) {
        servers[$1] = 1;
    }
}
END {
    mcount = asorti(minutes, smin);
    scount = asorti(servers, sserv);
    printf "minutes";
    for (col = 1; col <= scount; col++) {
        printf "," sserv[col] "-average," sserv[col] "-maximum";
    }
    print "";
    for (row = 1; row <= mcount; row++) {
        key = smin[row];
        printf key;
        for (col = 1; col <= scount; col++) {
            printf "," average[key, sserv[col]] "," maximum[key, sserv[col]];
        }
        print "";
    }
}

【讨论】:

    【解决方案2】:

    运行 awk 命令:./script.awk 文件

    #! /bin/awk -f
    BEGIN{
        FS=",";
        OFS=","
    }
    $1 ~ /server01/ && $3 ~ /Average/{
        a[$2]["Avg01"] = $4; 
    }
    $1 ~ /server01/ && $3 ~ /Max/{
        a[$2]["Max01"] = $4; 
    }
    $1 ~ /server02/ && $3 ~ /Average/{
        a[$2]["Avg02"] = $4; 
    }
    $1 ~ /server02/ && $3 ~ /Max/{
        a[$2]["Max02"] = $4; 
    }
    END{
        print "Minute","server01-AckDelayAverage","server01-AckDelayMax","server02-AckDelayAverage","server02-AckDelayMax"
        for(i in a){
            print i,a[i]["Avg01"],a[i]["Max01"],a[i]["Avg02"],a[i]["Max02"] | "sort"
        }
    }
    

    【讨论】:

      【解决方案3】:

      使用awksort

      awk -F, -v OFS=, '{
          a[$2]=(a[$2]?a[$2]","$4:$4)
      }
      END{
          for ( i in a ) print i,a[i]
      }' File | sort
      

      如果$4 具有0 值:

      awk -F, -v OFS=, '!a[$2]{a[$2]=$2} {a[$2]=a[$2]","$4} END{for ( i in a ) print a[i]}' | sort
      

      !a[$2]{a[$2]=$2}: 如果数组a 索引$2(分钟时间)不退出,数组a 索引为$2(分钟时间),值为@987654333 @ 被建造。当 Minute 第一次出现在队列中时为真。

      {a[$2]=a[$2]","$4}:将值 $4 连接到此数组

      END:打印数组a中的所有值

      最后通过管道将此 awk 结果进行排序。

      【讨论】:

      • 非常感谢,这在大多数情况下都能完美运行。我看到的一个观察结果是,如果分钟值的第一个指标为 0,则数据未正确转置。例如 server01,00:01:00,AckDelayAverage,0 server01,00:01:00,AckDelayMax,0 server01,00:02:00,AckDelayAverage,666 server01,00:02:00,AckDelayMax,5555
      • 猫测试 | awk -F, -v OFS=, '{a[$2]=(a[$2]?a[$2]","$4:$4)}END{for ( i in a ) print i,a[i]} ' 00:01:00,0 00:02:00,666,5555
      • 这不是因为分钟值,而是因为 '$4' 是 0 。我已经用解决方案编辑了答案以克服这个问题。
      • 谢谢。根据我的理解,你能解释一下第一部分是如何工作的吗? ( !a[$2]{a[$2]=$2} {a[$2]=a[$2]","$4)
      • 更新了答案。如果不清楚,您可以阅读awk array 的工作原理。
      猜你喜欢
      • 1970-01-01
      • 2015-11-09
      • 1970-01-01
      • 2014-06-22
      • 2020-07-19
      • 2020-10-28
      • 2016-08-26
      • 1970-01-01
      • 2023-03-19
      相关资源
      最近更新 更多