awk是一个强大的文本分析工具,简单地说,它是把文件逐行读入,以空格为默认分割符将每行切片,切开的部分再进行分析、处理。
使用方法
awk 'pattern + {action}' filenames
案例说明:
wusong@ubuntu:~$ last -n 5
wusong pts/9 192.168.58.1 Sat Sep 8 19:06 still logged in
wusong pts/9 192.168.58.1 Sat Sep 8 06:47 - 18:11 (11:24)
wusong pts/10 192.168.58.1 Fri Sep 7 20:24 - 21:21 (00:56)
wusong pts/9 192.168.58.1 Fri Sep 7 19:26 - 21:21 (01:55)
wusong pts/9 192.168.58.1 Fri Sep 7 06:45 - 18:56 (12:11)
wtmp begins Mon Sep 3 17:27:36 2018
wusong@ubuntu:~$ last -n 5 |awk '{print $1}'
wusong
wusong
wusong
wusong
wusong
wtmp
awk会读取有'\n'换行符分割的一条记录,然后将记录按指定的域分隔符划分域,1表示第一个域,$n表示第n个域。
cat /etc/passwd |awk -F ':' 'BEGIN {print "name,shell"} {print $1","$7} END {print "blue,/bin/nosh"}'
name,shell
root,/bin/bash
daemon,/bin/sh
bin,/bin/sh
sys,/bin/sh
....
blue,/bin/nosh
如果有BEGIN,就会先执行BEGIN,然后读取文件,读入有\n换行分割符的一条记录,对每条记录执行action,直到所有的记录都读完,最后执行end操作。
awk -F: '/root/' /etc/passwd // 搜索含有root关键字的行
root:x:0:0:root:/root:/bin/bash
awk -F: '/root/{print $7}' /etc/passwd
/bin/bash
awk内置变量
ARGC 命令行参数个数
ARGV 命令行参数排列
ENVIRON 支持队列中系统环境变量的使用
FILENAME awk浏览的文件名
FNR 浏览文件的记录数
FS 设置输入域分隔符,等价于命令行 -F选项
NF 浏览记录的域的个数
NR 已读的记录数
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符
wusong@ubuntu:~$ awk -F ':' '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd
filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash
filename:/etc/passwd,linenumber:2,columns:7,linecontent:daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/usr/sbin/nologin
filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/usr/sbin/nologin
filename:/etc/passwd,linenumber:5,columns:7,linecontent:sync:x:4:65534:sync:/bin:/bin/sync
filename:/etc/passwd,linenumber:6,columns:7,linecontent:games:x:5:60:games:/usr/games:/usr/sbin/nologin
filename:/etc/passwd,linenumber:7,columns:7,linecontent:man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
filename:/etc/passwd,linenumber:8,columns:7,linecontent:lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
filename:/etc/passwd,linenumber:9,columns:7,linecontent:mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
可以使用printf代替print,让代码更加简洁
awk -F ':' '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd
awk除了内置变量,还可以自定义变量。
- 统计/etc/passwd的账户人数
awk '{count++;print $0;} END{print "user count is ", count}' /etc/passwd
- 统计某个文件夹下的文件占用的字节数
wusong@ubuntu:~$ ls -l | awk 'BEGIN {size=0;} {size=size+$5;}END{print "size is", size}'
size is 63307
wusong@ubuntu:~$ ls -l | awk 'BEGIN {size=0;} {size=size+$5;}END{print "size is", size/1024/1024 " M"} '
size is 0.0603743 M // 不包括文件夹的子目录
- awk 使用数组
awk -F: 'BEGIN{count=0;} {name[count]=$1; count++;} END { for (i=0;i<NR;i++) print i, name[i]}' /etc/passwd
几个小例子
- 统计tcp连接状态
wusongs-MacBook-Pro:~ wusong$ netstat -n | awk '/^tcp/{++test[$NF]} END {for (a in test) print a, test[a]}'
CLOSE_WAIT 3
TIME_WAIT 1
ESTABLISHED 28
S[]定义了一个名叫S的数组,在awk中,数组下标通常从 1 开始,而不是 0。
NF当前记录里域个数,默认以空格分隔,如上所示的记录,NF域个数等于6
$NF表示一行的最后一个域的值,$NF也就是$6,表示第6个字段的值,也即SYN_RECV或TIME_WAIT等。
S[$NF] 表示数组元素的值,如上所示的记录,就是S[TIME_WAIT]状态的连接数++S[$NF]表示把某个数加一,如上所示的记录,就是把S[TIME_WAIT]状态的连接数加1
END for(key in S)遍历S[]数组 print key,”\t”,S[key],打印数组的键和值,中间用\t制表符分割,显示好一些。
- 统计apache日志单ip访问请求数排名
awk '{++S[$1]} END {for(i in S) print i, S[i]}' access.log | sort -k2 -r
10.0.0.41 3
10.0.0.47 2
10.0.0.46 2
10.0.0.42 2
10.0.0.43 1
- 查看linux系统上的所有用户
wusong@ubuntu:~$ awk 'BEGIN{
FS=":"
printf("%-10s%-20s\n", "UserName", "HomeDir")
print "=============================="
}
{
printf("%-10s%-20s\n", $1, $6)
}
END{
print "=============================="
printf("User(s):%d\n", NR)
print "=============================="
}' /etc/passwd
也可以将上述脚本写入listUser.awk这个文件,然后在命令行中执行:
awk -f listUser.awk /etc/passwd
透过现象看本质
image.png上图为awk的基本流程,awk分为三个部分:
- BEGIN(必须大写),初始化模块,进行分隔符的定义,初始化一些变量等,它在数据处理部分之前执行,且只执行一次,BEGIN模块是可选的。
- 数据处理模块。这一部分是awk脚本的核心部分,它是一对以pattern与大括号括起来的action组合而成,两者可能会出现以下组合:
- pattern {action} :记录(每行为一个记录)匹配对应的模式,则执行大括号中的操作
- pattern 记录匹配所有的模式,直接打印记录。
- {action} 对每一条记录都执行大括号中的操作
- 数据处理模块会循环读取待处理文件中的记录,读一条处理一条,处理完再读下一条。
- END(必须大写),最后的收尾处理模块。它会在所有的数据处理完毕后执行,END模块同BEGIN一样只执行一次并且也是可选的。
小结
本文主要介绍了awk的基本用法和一些小的案例以及awk流程分析,awk是一种功能极其强大的文本分析工具,值得深入研究。
网友评论