若何统计日志中,调用某个接口的耗时呢?
此时的需求就是对文本进行复杂的格式处理,那么我们就自然的想到了awk命令。
1. awk语法分析
1. awk的基础语法:
awk [options] 'Pattern{Action}' file
options操作,我们可以指定一些特殊的操作,例如输入分割符,将字符串按照特定的输入进行分割。
-
Pattern模式,我们可以看做为【条件】,即满足条件(模式)的行才会被处理。一般有
- 【空模式和关系表达式模式】:awk 'NF==5 {print $0}' test,即满足关系运行符的模式。
- 【BEGIN模式和END模式】:awk 'BEGIN{print "aaa","bbb"}{print 2}'即在处理文本之前或之后的模式。
- 【正则模式】:awk '/正则表达式/{print $0}' /etc/passwd,即把正则表达式作为条件
- 【行范围模式】:awk '/正则1/,/正则2/{动作}' file,即匹配正则1和正则2之间的行。
action动作,
{}
属于【组合语句】类型的动作,组合语句是将多个代码组合成代码块。例如:awk '{ if(NR==1){print $0} }' file。
2. shell脚本参数值
在awk命令中,$1是内置变量,代表的是分割的第一行。
使用options中的-v参数,来声明引用的变量。
在参数传递进来是,赋值给变量,后续直接使用该变量,需要注意的是,在awk命令中,不管是内置变量,还是自定义变量,都不使用$,而是直接使用变量名。
需要注意的是,在shell脚本中,使用$来引用变量。
3. 代码编写
1. 效果图
2. 执行代码
#!/bin/sh
fileName=$1
timeout=$2
echo "[响应时间统计]-[开始]"
##################################################
echo "[统计时间参数准备]-[文件名]-[$fileName]"
echo "[统计时间参数准备]-[时间界限]-[$timeout]"
##################################################
##使用awk正则表达式获取符合条件的行,取第九列:格式:【共耗时-3304-毫秒】【购买单笔-响应】->{"retCode":"4954","retInfo":"响应码不存在","data":{"XML_OUT_CONTENT":"00001220
awk -v fileName=$fileName '/【购买单笔-响应】/{print $9}' ../log/$fileName |
awk -v timeout=$timeout -F- '{if($2>timeout){print $2}}' |sort -rn | xargs | #[-F awk的分割符,打印第2列][-r是降序排列 -n 是按数字排序][xargs 将列变为一行数据]
awk 'BEGIN{print "[统计时间结果准备]-[开始]"}
{for(i=1;i<=NF;i++)
{sum+=$i}
if(NF==0){
printf "%s\n","[统计时间结果]-[日志中没有符合条件的数据]";
exit
}
printf "[平均值]-[%s%s]\n",sum/NF,"ms"}
{printf "[最大值]-[%s%s]\n",$1,"ms"}
{printf "[最小值]-[%s%s]\n",$NF,"ms"}
END{printf "%s%s%s]\n","[响应时间统计结束]-[共统计",NF,"条数据"}'
- 使用pattern中的【正则表达式模式】设置条件,只有处理满足条件的资源,才能进行Action操作【此处是截取第9列】。
- 使用options中的【-F-】选项,以【-】来截取获取到的资源。设置Action的动作是
'{if($2>timeout){print $2}}'
。 - sort的option:-n 依照数组大小排序,-r 以相反的顺序(降序)排序。
- awk的内置变量NR是行号,NF是每行的列数。我们此时需要将多行数据设置为一行,即将【标记意义的空格(换行、制表)】转化为【文本意义上的空格】,故使用xargs命令。
- 使用exit命令,并不是退出整个awk命令,而是直接执行END模式中的动作。
- action中{}是组合动作,即包含一组动作。
- printf命令是格式化输出,%s是字符串类型。