• awk处理实记


    经grep日志后得到的数据格式如下:

    }
     .
    [debug][2019-05-20 00:00:00] SendDataStyled:{
       "cmd" : 0001,
       "innings" : "6189269620_0007",
       "players" : [
          {
             "al_board" : 1,
             "al_win" : 1,
             "alter_exp" : 0,
             "alter_money" : 10,
             "uid" : 34329592
          },
          {
             "al_board" : 1,
             "al_win" : 0,
             "alter_exp" : 0,
             "alter_money" : -26,
             "uid" : 13416009
          },
          {
             "al_board" : 1,
             "al_win" : 1,
             "alter_exp" : 0,
             "alter_money" : 16,
             "uid" : 41165640
          }
       ],
       "roomid" : "6189269620",
       "vid" : 1205
    }

    希望将一条原始数据处理后,生成若干条以下格式的数据:

    time al_win alter_money uid roomid

    由于很久没有用过awk了,先复习了一遍语法做了些小实验才正式开始。经过整理后的思考路径如下:

    1. 确定分隔符。 原本是想用空格,“[”, “]”,三个符号做分隔的,实验后发现由于打印格式的问题,很多字段前面都有很多个空格,这样不太好数需要的字段编号。所以最后分隔符定为中括号,双引号,冒号,逗号。
    2. 确定所需字段分隔后的编号。 根据分隔符数一下,然后通过命令行验证一下就可以了。这个还是很容易且快的。
    3. 思考如何组织并输出数据。 基本想法是除了要重复用到的time和roomid保存一下,其它字段是拿到后就直接打印,读取uid之后,打印uid及roomid就进行换行。有点困难的是roomid的读取,因为awk是按行顺序处理的,一个uid打印一行数据的话就等不到读后面的roomid了。幸好发现在数据innings里实际上隐含着roomid,拿到innings后用“_”截取前面一段就可以了。
    4. 实操。

    整个路径看起来是挺简单的,实际上用了我好几个小时才写出了完整可用的awk。特此记录下遇到的问题及得到教训。

    1. 尽量用awk脚本写,不要在命令行直接写。 也是因为只稍微复习了下语法就开始的原因,不知道可直接写在文件里调用,在命令行写极易出错,不易阅读,而且修改起来相当痛苦。
    2. 自定义变量的生命周期。 不说太深,只说现今用到的。awk我们日常用到的自定义变量基本都是全局变量,直接使用就可以了。只是要注意下自己的程序应当在什么时候对变量进行初始化。如果只初始化一次,就在BEGIN里写;如果需要在具体的行里多次初始化,在BEGIN不用初始化也可以直接用。
    3. 变量的使用。 也是由于复习不到位的问题,没有注意到使用变量时不需要使用$,比如要打印NF变量,直接print NF即可。因为这个小问题,走了不少弯路,深刻的教训。
    4. printf 的随意性。 如果没有定义具体的打印格式,printf后接空格,再接要打印的变量名或字段就可以了,用逗号或空格分隔都可以。要打印的所有变量可以用小括号包起来,也可以不包起来。不得不说,真的是强!
    5. 定义分隔符在命令行和脚本里的不同。 以上文确定的分隔符为例,在命令行应该写作 -F '[][":,]' , 在脚本里则应该在BEGIN里写成 FS="[][":,]"; 。

    最后,贴上写完的脚本:

    source.awk

    BEGIN {
    FS="[][":,]";
    }
    
    {
    if($4~/2019-/) a=$4":"$5":"$6;
    else if($2~/innings/) split($5, b, "_");
    else if($2~/al_win/) printf a $4;
    else if($2~/alter_money/) printf $4;
    else if($2~/uid/) printf "%s %s
    ", $4, b[1];
    }

    直接使用 awk -f source.awk data.log > res.txt 即可。

    另附参考的awk基础知识:

    https://www.cnblogs.com/xudong-bupt/p/3721210.html

  • 相关阅读:
    [NOI2010]航空管制
    [POI2008]POD-Subdivision of Kingdom
    CF17C Balance
    [HAOI2007]理想的正方形
    [Code+#1]大吉大利,晚上吃鸡!
    HDU 3371
    hdu1102
    最短路算法、应用、模板总结
    csu十月月赛 并查集+分组背包
    csu 十月月赛 最短路+最小费用
  • 原文地址:https://www.cnblogs.com/RookieSuperman/p/10936480.html
Copyright © 2020-2023  润新知