一、awk简单解释
二、BEGIN和END模块
三、awk处理数据的流程
1.进行逐行扫描文件, 从第一行到最后一行
2.寻找匹配的特定模式的行,在行上进行操作
3.如果没有指定处理动作,则把匹配的行显示到标准输出
4.如果没有指定模式,则所有被操作的行都被处理
四、awk语法
awk [options] 'commands' filenames
awk [options] -f awk-script-file filenames
五、awk参数
awk [-F|-f|-v] ‘BEGIN{} //{command1; command2} END{}’ file
[-F|-f|-v] 大参数,-F指定分隔符,-f调用脚本,-v定义变量 var=value
' ' 引用代码块
BEGIN 初始化代码块,在对每一行进行处理之前,初始化代码,主要是引用全局变量,设置FS分隔符
// 匹配代码块,可以是字符串或正则表达式
{} 命令代码块,包含一条或多条命令
; 多条命令使用分号分隔
END 结尾代码块,在对每一行进行处理之后再执行的代码块,主要是进行最终计算或输出结尾摘要信息
$0 表示整个当前行
$1 每行第一个字段
NF 字段数量变量
NR 每行的记录号,多文件记录递增
FNR 与NR类似,不过多文件记录不递增,每个文件都从1开始
\t 制表符
\n 换行符
FS BEGIN时定义分隔符
RS 输入的记录分隔符, 默认为换行符(即文本是按一行一行输入)
~ 匹配,与==相比不是精确比较
!~ 不匹配,不精确比较
== 等于,必须全部相等,精确比较
!= 不等于,精确比较
&& 逻辑与
|| 逻辑或
+ 匹配时表示1个或1个以上
/[0-9][0-9]+/ 两个或两个以上数字
/[0-9][0-9]*/ 一个或一个以上数字
FILENAME 文件名
OFS 输出字段分隔符, 默认也是空格,可以改为制表符等
ORS 输出的记录分隔符,默认为换行符,即处理结果也是一行一行输出到屏幕
-F'[:#/]' 定义三个分隔符
六、awk基础工作
1、匹配root
[root@1 liangzeyu]# awk '/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
dockerroot:x:995:992:Docker User:/var/lib/docker:/sbin/nologin
2、-F执行:为分隔符,取除第一列
awk -F: '{print $1}' /etc/passwd
3、打印匹配root的行的第一列和第三列
[root@1 liangzeyu]# awk -F: '/root/{print $1,$3}' /etc/passwd
root 0
operator 11[root@1 ~]# awk 'BEGIN{FS=":"} /root/{print $1}' /etc/passwd
root
4、判断/目录如果大于50000则打印(如果/目录使用了50000以上,则打印剩余空间)
[root@1 ~]# df|awk '/\/$/ {if ($3>50000) print $4}'
14598656
七、awk内置变量
1、$0表示$1-$$(第一列到最后一列)
awk '{print $0}' /etc/passwd
2、NR表示行号
[root@1 ~]# awk '{print NR,$0}' /etc/passwd
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3、只查看前3行内容
[root@1 ~]# awk 'NR<=3' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
4、FNR 当前文件的编号(行号)
awk '{print FNR,$0}' /etc/passwd test.txt
5、NF 最后一列
[root@1 liangzeyu]# awk -F: '{print $NF}' /etc/passwd
/bin/bash
6、FS是指定的分隔符(默认分隔符是1个空格)
[root@1 liangzeyu]# awk -F: '/root/{print $1,$3}' /etc/passwd
root 0
operator 11[root@1 ~]# awk 'BEGIN{FS=":"} /root/{print $1}' /etc/passwd
root
7、指定:号和多个空格为分割符
awk -F'[:| ]+' '{print $1}' /etc/passwd
8、OFS执行输出字段分隔符
[root@1 liangzeyu]# awk 'BEGIN{FS=":";OFS="+++"} /root/{print $1,$2}' /etc/passwd
root+++x
operator+++x[root@1 liangzeyu]# awk 'BEGIN{FS=":"} /root/{print $1"+++"$2}' /etc/passwd
root+++x
operator+++x
9、RS输入记录分隔符,默认为换 行符
awk -F: 'BEGIN{RS=" "} {print $0}' /etc/hosts
10、`ORS`将文件以空格为分割每一行合并为一行
awk -F: 'BEGIN{ORS=" "} {print $0}' /etc/hosts
11、函数输出
awk -F: '{print "用户是:" $1 "\t 用户uid: " $3 "\t 用户gid:" $4}' /etc/passwd
12、第一列是root的,显示整行内容
[root@1 liangzeyu]# awk -F: '$1 ~ /root/{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
dockerroot:x:995:992:Docker User:/var/lib/docker:/sbin/nologin
13、第一列不是root的。显示整行内容
awk -F: '$1 !~ /root/{print $0}' /etc/passwd
八、比较运算符
运算符 含义 示例
< 小于 x<y
<= 小于或等于 x<=y
== 等于 x==y
!= 不等于 x!=y
>= 大于等于 x>=y
> 大于 x>y
uid为0的列出来
[root@Shell ~]# awk -F ":" '$3==0' /etc/passwd
uid小于10的全部列出来
[root@Shell ~]# awk -F: '$3 < 10' /etc/passwd
用户登陆的shell等于/bin/bash
[root@Shell ~]# awk -F: '$7 == "/bin/bash" ' /etc/passwd
第一列为alice的列出来
[root@Shell ~]# awk -F: '$1 == "alice" ' /etc/passwd
为alice的用户列出来
[root@Shell ~]# awk -F: '$1 ~ /alice/ ' /etc/passwd
[root@Shell ~]# awk -F: '$1 !~ /alice/ ' /etc/passwd
磁盘使用率大于多少则,则打印可用的值
[root@Shell ~]# df |awk '/\/$/'|awk '$3>1000000 {print $4}'
九、条件表达式
[root@Shell ~]# awk -F: '$3>300 {print $0}' /etc/passwd
[root@Shell ~]# awk -F: '{if($3>300) print $0}' /etc/passwd
[root@Shell ~]# awk -F: '{if($3>5555){print $3} else {print $1}}' /etc/passwd
十、运算表达式
[root@Shell ~]# awk -F: '$3 * 10 > 500000' /etc/passwd
[root@Shell ~]# awk -F: 'BEGIN{OFS="--"} { if($3*10>50000) {print $1,$3} } END {print "打印ok"}' /etc/passwd
[root@Shell ~]# awk '/southem/{print $5 + 10}' datafile
[root@Shell ~]# awk '/southem/{print $5 + 10.56}' datafile
[root@Shell ~]# awk '/southem/{print $8 - 10}' datafile
[root@Shell ~]# awk '/southem/{print $8 / 2 }' datafile
[root@Shell ~]# awk '/southem/{print $8 * 2 }' datafile
[root@Shell ~]# awk '/southem/{print $8 % 2 }' datafile
十一、逻辑操作符和复合模式
&&逻辑与 || 逻辑或 !逻辑非
匹配用户名为root并且打印uid小于15的行
[root@Shell ~]# awk -F: '$1~/root/ && $3<=15' /etc/passwd
匹配用户名为root或uid大于5000
[root@Shell ~]# awk -F: '$1~/root/ || $3>=5000' /etc/passwd
十二、判断语句
if语句格式:{ if(表达式){语句;语句;... }}
打印当前管理员用户名称
[root@Shell ~]# awk -F: '{ if($3==0){print $1 "is adminisitrator"} }' /etc/passwd
统计系统用户数量
[root@Shell ~]# awk -F: '{ if($3>0 && $3<1000){i++}} END {print i}' /etc/passwd
统计普通用户数量
[root@Shell ~]# awk -F: '{ if($3>1000){i++}} END {print i}' /etc/passwd
if...else 语句格式: {if(表达式){语句;语句;... }else{语句;语句;...}}
# awk -F: '{if($3==0){print $1} else {print $7}}' /etc/passwd
# awk -F: '{if($3==0) {count++} else{i++} }' /etc/passwd
# awk -F: '{if($3==0){count++} else{i++}} END{print " 管理员个数: "count ; print " 系统用户数: "i}' /etc/passwd
if...else if...else 语句格式:
{if(表达式 1){语句;语句;... }else if(表达式 2){语句;语句;. .. }else{语句;语句;... }}
[root@Shell ~]# awk -F: '{ if($3==0){i++} else if($3>0 && $3<1000){j++} else if($3>1000) {k++}} END {print i;print j;print k}' /etc/passwd
[root@Shell ~]# awk -F: '{ if($3==0){i++} else if($3>0 && $3<1000){j++} else if($3>1000) {k++}} END {print "管理员个数"i; print "系统用户个数" j; print "系统用户个 数" }' /etc/passwd
管理员个数1
系统用户个数29
系统用户个数69
十三、while循环语句
[root@Shell ~]# awk 'BEGIN{ i=1; while(i<=10){print i; i++} }'
[root@Shell ~]# awk -F: '{i=1; while(i<=NF){print $i; i++}}' /etc/passwd
[root@Shell ~]# awk -F: '{i=1; while(i<=10) {print $0; i++}}' /etc/passwd
[root@Shell ~]#cat b.txt
111 222
333 444 555
666 777 888 999
[root@Shell ~]# awk '{i=1; while(i<=NF){print $i; i++}}' b.txt
十四、for循环
[root@Shell ~]# awk 'BEGIN{for(i=1;i<=5;i++){print i} }'
将每行打印 10 次
[root@Shell ~]# awk -F: '{ for(i=1;i<=10;i++) {print $0} }' passwd
[root@Shell ~]# awk -F: '{ for(i=1;i<=10;i++) {print $0} }' passwd
[root@Shell ~]# awk -F: '{ for(i=1;i<=NF;i++) {print $i} }' passwd
十五、数组
1、统计`/etc/passwd`中各种类型`shell` 的数量
awk -F: '{shells[$NF]+ +} END{ for(i in shells){print i,shells[i]} }' /etc/passwd
2、站访问状态统计<当前时实状态ss>
[root@Shell ~]# ss -an|awk '/:80/{tcp[$2] ++} END {for(i in tcp){print i,tcp[i]}}'
3、 统计当前访问的每个IP的数量<当前时实状态 netstat,ss>
ss -an|awk -F ':' '/:80/{ips[$(NF-1)]++} END {for(i in ips){print i,ips[i]}}'
十六、日志分析
1、统计2018年01月25日,当天的PV量
[root@Shell ~]# grep "25/Jan/2018" log.bjstack.log |wc -l
[root@Shell ~]# awk "/25\/Jan\/2018/" log.bjstack.log |wc -l
[root@Shell ~]# awk '/25\/Jan\/2018/ {ips[$1]++} END {for(i in ips) {sum+=ips[i]} {print sum}}' log.bjstack.log
2、统计15-19点的pv
[root@Shell ~]# awk '$4>="[25/Jan/2018:15:00:00" && $4<="[25/Jan/2018:19:00:00 {print $0}"' log.bjstack.log |wc -l
3、统计2018年01月25日,一天内访问最多的10个IP*
[root@Shell ~]# awk '/25\/Jan\/2018/ {ips[$1]++} END {for(i in ips){ print ips[i],i}}' log.bjstack.log |sort -rn|head
4、统计15-19点访问次数最多的10个IP
[root@Shell ~]# awk '$4>="[25/Jan/2018:15:00:00" && $4<="[25/Jan/2018:19:00:00"' log.bjstack.log |awk '{ips[$1]++} END {for(i in ips){print ips[i],i}}'|sort -rn|head
5、统计2018年01月25日,访问大于100次的IP
[root@Shell ~]# awk '/25\/Jan\/2018/ {ips[$1]++} END {for(i in ips){if(ips[i]>10){print i,ips[i]}}}' log.bjstack.log
6、统计2018年01月25日,访问最多的10个页面($request top 10)
[root@Shell ~]# awk '/25\/Jan\ /2018/ {request[$7]++} END {for(i in request){print request[i],i}}' log.bjstack.log |sort -rn| head
7、统计2018年01月25日,每个URL访问内容总大小($body_bytes_sent)*
awk '/25\/Jan\/2018/ {request[$7]++;size[$7]+=$10} END {for(i in request){print request[i],i,size[i]}}' log.bjstack.log |sort -rn|head
8、统计2018年01月25日,每个IP访问状态码数量($status)*
awk '{ip_code[$1 " " $9]++} END {for(i in ip_code){print ip_code[i],i}}' log.bjstack.log|sort -rn|head
9、统计2018年01月25日,访问状态码为404及出现的次数($status)*
grep "404" log.bjstack.log |wc -l
awk '{if($9=="404") code[$9]++} END {for(i in code){print i,code[i]}}' log.bjstack.log
10、统计2018年01月25日,8:30-9:00访问状态码是404*
awk '$4>="[25/Jan/2018:15:00:00" && $4<="[25/Jan/2018:19:00:00" && $9=="404" {code[$9]++} END {for(i in code){print i,code[i]}}' log.bjstack.log
awk '$9=="404" {code[$9]++} END {for(i in code){print i,code[i]}}' log.bjstack.log
11、统计2018年01月25日,各种状态码数量,统计状态码出现的次数
[root@Shell ~]# awk '{code[$9]++} END {for(i in code){print i,code[i]}}' log.bjstack.log
[root@Shell ~]# awk '{if($9>=100 && $9<200) {i++}
else if ($9>=200 && $9<300) {j++}
else if ($9>=300 && $9<400) {k++}
else if ($9>=400 && $9<500) {n++}
else if($9>=500) {p++}}
END{print i,j,k,n,p,i+j+k+n+p}' log.bjstack.log
有问题请加博主微信进行沟通!
全部评论