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)

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

时间: 2024-11-03 23:43:22

awk随笔的相关文章

linux 中awk 学习随笔

awk awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理. 常用案例:  awk内置对象: ARGC               命令行参数个数ARGV               命令行参数排列ENVIRON            支持队列中系统环境变量的使用FILENAME           awk浏览的文件名FNR       

grep及正则表达式随笔

grep [acivn] [--color=auto] '查找字符串' filename -a:将binary文件以text文件的方式查找数据 -c:计算找到'查找字符串'的次数 -i:忽略大小写 -v:反向选择 -n:将查找结果列出行号 --color=auto:查找结果中关键字着色 **********grep使用例子********** (1)列出一个目录下目录的名称: ll |grep '^d' |awk '{print $9}' 其中awk中$后面是列的位置 (2)列出一个文件,去除空

python,第一次课堂随笔

第一次接触python就是在上python课程的时候,对于这一门语言从来没有去研究过,可以说是小白,完全不了解.更是不知道这门语言的作用和特性.这次的随笔可以说是第一次去了解python的机会了. Python的设计目标之一是让代码具备高度的可阅读性.它设计时尽量使用其它语言经常使用的标点符号和英文单字,让代码看起来整洁美观.它不像其他的静态语言如C.Pascal那样需要重复书写声明语句,也不像它们的语法那样经常有特殊情况和意外. Python的设计哲学是"优雅"."明确&q

新awk整理

总感觉上一篇awk的总结几乎是照着man翻译过来的,惨不忍睹 无意间在互联网上有找到了宝贵的资料 感觉整理的很好,想着照着这个来重新写下,对照新的man更新下吧,只是总是在改变的 一.awk简介二.awk工作流程三.awk程序结构四.awk基本语法 awk命令行模式 awk程序文件 awk标准选项五.awk内置变量 标准awk变量 awk特定变量(即专有变量)六.awk操作符 算数运算符 关系运算符 逻辑运算符 三元运算符 一元运算符 字符串连接操作符(即空格符) 数组成员操作符(in) 正则表

linux提取指定列字符并打印所有内容(awk)

假设有文件长如下样子: CHROM  POS     ID      REF     ALT     QUAL    FILTER  INFO    FORMAT  samplename 1 3552841 . G . 32.995 . DP=1;MQ0F=0;AF1=0;AC1=0;DP4=1,0,0,0;MQ=40;FQ=-29.9912 GT:PL:DP 0/0:0:1 1 3552842 . T . 32.995 . DP=1;MQ0F=0;AF1=0;AC1=0;DP4=1,0,0,0

shell之awk

简介 awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行读入,以空格为默认分割符将每行切片,切开的部分再进行各种分析处理. 使用方法: awk [option] 'pattern1{action1}pattern2{action2}' {filenames} 尽管操作可能会很复杂,但语法总是这样,其中pattern表示awk在数据中查找的内容,而action是在找到匹配内容时所执行的一系列命令. awk

awk中使用shell变量

其实在awk里,是不能直接使用shell变量的 方法是:awk -v 选项让awk 里使用shell变量 TIME=60 awk -v time="$TIME" 'BEGIN{FS="|"} {if ($7>time) print $2 }' 这样要注意:在awk里,time不能加$符号. 网上说如下方法都可行: 一:"'$var'" 这种写法大家无需改变用'括起awk程序的习惯,是老外常用的写法.如: var="test&quo

awk 字符串处理函数

awk提供了许多强大的字符串函数,见下表:awk内置字符串函数gsub(r,s)    在整个$0中用s替代rgsub(r,s,t)    在整个t中用s替代rindex(s,t)    返回s中字符串t的第一位置length(s)    返回s长度match(s,r)    测试s是否包含匹配r的字符串split(s,a,fs)    在fs上将s分成序列asprint(fmt,exp)    返回经fmt格式化后的expsub(r,s)    用$0中最左边最长的子串代替ssubstr(s,

awk

cat 1.txt 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 行转列: awk '{for(i=1;i<=NF;i++)printf("%s\n",$i)};{printf "\n"}' 1.txt 显示如下: 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9