awk随笔

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了awk随笔相关的知识,希望对你有一定的参考价值。

 

在对日志信息进行实时监控分析时,需要对日志中纳秒级的时间进行计算,逻辑比较简单:找出开始时间、结束时间,遇到结束时间后输出时间间隔。

日志中的部分数据如下:

2016-01-30 19:37:30 1454153850967748663 remove alive file
2016-01-30 19:37:34 1454153854621122459 role change to FAULT

 

一开始写出来是这样的:

awk /remove alive file/ {
  start=$3
  printf "%6s: %d\n","START",start
}
/role change to FAULT/ {
  end=$3;
  printf "%6s: %d\n","END",end
  diff=(end-start)/1000^3
  printf "%6s: %0.9f(s)\n","DIFF",diff
}

输出结果看似就是我想要的:

 START: 1454153850967748608
   END: 1454153854621122560
  DIFF: 3.653373952(s)

 

有的朋友可能看到这个结果后就直接使用了,但是较真的我还是把输出结果和bc的结算结果比较了一下,没问题。

接下来我习惯性的到日志中把每个输出结果进行确认,略一看没什么不对的地方,仔细一对比,发现日志中纳秒级的时间被awk处理后竟然变了(GNU Awk 3.1.7)。为了进行确认,写了如下代码:

awk BEGIN {
  printf "%20s == %-20s\n","0X2FFFFFFFFFFFFF","13510798882111487"
  printf "%20X    %d\n",0X2FFFFFFFFFFFFF,0X2FFFFFFFFFFFFF
  printf "%20X    %d\n",13510798882111487,13510798882111487
  printf "---------------------------------------------\n"
  printf "%20s == %-20s\n","0X2FFFFFFFFFFFFE","13510798882111486"
  printf "%20X    %d\n",0X2FFFFFFFFFFFFE,0X2FFFFFFFFFFFFE
  printf "%20X    %d\n",13510798882111486,13510798882111486
}

输出结果如下:

    0X2FFFFFFFFFFFFF == 13510798882111487   
      30000000000000    13510798882111488
      30000000000000    13510798882111488
---------------------------------------------
    0X2FFFFFFFFFFFFE == 13510798882111486   
      2FFFFFFFFFFFFE    13510798882111486
      2FFFFFFFFFFFFE    13510798882111486

对应的二进制数值如下:

0X30000000000000: 11 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0X2FFFFFFFFFFFFF: 10 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111
0X2FFFFFFFFFFFFE: 10 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110

发现awk的数值处理范围超过0X2FFFFFFFFFFFFE(13510798882111486)就不不准确了(为了找这个临界值,费了一番功夫),他会把0X2FFFFFFFFFFFFF当成0X30000000000000,如果在awk中对0X2FFFFFFFFFFFFF进行减一计算,值没有任何变化,对0X2FFFFFFFFFFFFE进行加法运算,加1和加2的结果都是0X30000000000000,但是awk又可以显示/处理更大的数值,从二进制结果中我也没看出有什么规律可循。有兴趣的可以深入源码层面研究下。

 

接下来,毅然放弃awk自身的计算功能,选择awk与bc的结合。于是,把代码修改成下面的样子:

awk /remove alive file/ {
  start=$3
  printf "%6s: %s\n","START",start
}
/role change to FAULT/ {
  end=$3
  printf "%6s: %s\n","END",end
  printf "%6s: %0.9f(s)\n","DIFF",system("echo \"scale=9; ("end" - "start")/1000^3\"|bc")
}

 

输出结果如下:

 START: 1454153850967748663
   END: 1454153854621122459
3.653373796
  DIFF: 0.000000000(s)

awk的system无法把输出结果传递到awk,于是继续改,用getline实现:

awk /remove alive file/ {
  start=$3
  printf "%6s: %s\n","START",start
}
/role change to FAULT/ {
  end=$3
  printf "%6s: %s\n","END",end
  "echo \"scale=9; ("end" - "start")/1000^3\"|bc"|getline diff
  printf "%6s: %0.9f(s)\n","DIFF",diff
}

输出结果如下:

 START: 1454153850967748663
   END: 1454153854621122459
  DIFF: 3.653373796(s)

 

至此,终于得到使我满意的结果。

 

以上是关于awk随笔的主要内容,如果未能解决你的问题,请参考以下文章

Linux操作随笔

ROSETTA使用技巧随笔

linux学习随笔3之linux安全

经济随笔

如何计算bash中一列数据中的连续重复次数?

日常学习随笔-自定义了一个双链表(注释蛮详细的)