我想应该先看看awk程序基本结构,pattern { action },基本操作就是一行行进行文本扫描,找出匹配模式的行,然后执行相应的动作,所有行读取完毕结束。
先看一个最简单的例子,trace.log文件包含姓名、年龄、工龄。
star 25 1
moon 32 5
sun 29 3
river 27 4
lake 30 6
sea 35 8
你现在想找出工龄大于等于5年的员工(整行),一句话的事,在pattern部分直接写你需要的表达式,$0用来标识一整行
awk '$3 >= 5 {print $0}' trace.log
1
结果:
moon 32 5
lake 30 6
sea 35 8
你想给输出加个行号,一点也不过分,awk提供了内建变量 NR
awk '$3 >= 5 {print NR,$0}' trace.log
1
结果:
2 moon 32 5
5 lake 30 6
6 sea 35 8
你想使用printf格式化输出下,那是你自己的事
awk '$3 >= 5 {printf("name: %s,age: %d \n",$1,$2)}' trace.log
1
结果酱紫:
name: moon,age: 32
name: lake,age: 30
name: sea,age: 35
通常使用awk都是只有action,输出你关心的分段数据,其实绝妙之处还是在pattern,你只想看看姓名是moon的数据
awk '$1 == "moon"' trace.log # moon 32 5
1
pattren可以使用组合,使用括号,与&&,或||,非!
awk '$2 >30 && $3 >= 8' trace.log # sea 35 8
1
说了这么多,还是没有意思,也许统计会对你有些许用处,首先你要明白两点:END关键字用于匹配最后一行之后的位置,你可以在创建自己的变量用于计算但无需声明。你想看下工作年限超过5年的有几个人
awk '$3 >= 5 {total += 1} END {print "超过5年:",total,"人"}' trace.log
1
一行一行的扫描像极了循环,循环过程中你可以开始你的表演(计算),END匹配到最后一行之后,然后搞点动作
现在你学会求和了,你想看看员工的平均年龄,别忘了NR记录了行数
awk '{total += $2} END {print total/NR}' trace.log
1
你想看看年龄的一般水平,也许中位数更具有代表性,你应该先排个序
awk '{print $2," ", $3," " $1}' trace.log | sort
1
接着找到中间位置的数据就OK了
awk '{print $2," ", $3," " $1}' trace.log | sort | awk '{line[NR] = $1} END {print line[int(NR/2)]}'
1
你还想看看年龄的最大值,最小值,有了上面的经验,简直不要太esay
awk '{print $2," ", $3," " $1}' trace.log | sort | awk '{line[NR] = $0} END {print line[1],"\n",line[NR]}'
还有一个BEGIN关键字没有说,和END类似,不赘述了,画个图总结下: