awk在实际的使用过程中,更多的文本类型进行处理,使用好了Linux三大剑客之一的awk,在shell编程、Linux运维等等中如鱼得水,官方链接学习链接如下:
http://www.gnu.org/software/gawk/manual/gawk.html
![e550312034166b383d03d301c61b34d6.png](https://i-blog.csdnimg.cn/blog_migrate/9ab50c446fe40b798da5fdb749fce4db.jpeg)
由于是英文版且访问的蜗牛速度,还是通过简单直接的例子来实现快速入门!
1、创建一个文本并初始化内容
message.txt 文件
Proto Recv-Q Send-Q Local-Address Foreign-Address Statetcp 0 4166 localhost:80 61.148.242.38:30901 ESTABLISHEDtcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTENtcp 0 0 0.0.0.0:80 0.0.0.0:* LISTENtcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTENtcp 0 0 localhost:80 111.205.5.146:18222 TIME_WAITtcp 0 0 localhost:80 640.101.225:3753822 FIN_WAIT2tcp 0 0 localhost:80 111.104.224.189:1222 ESTABLISHEDtcp 0 0 localhost:80 111.109.224.111:42209 ESTABLISHEDtcp 0 0 localhost:80 111.204.227.77:11222 FIN_WAIT2tcp 0 0 localhost:80 111.109.224.111:42229 ESTABLISHEDtcp 0 0 localhost:80 111.60.222.36:36922 TIME_WAITtcp 0 4166 localhost:80 611.108.222.38:30221 ESTABLISHEDtcp 0 1 localhost:80 11 0 22 22tcp 0 1 localhost:80 111.102.221.209:22225 FIN_WAIT1tcp 0 0 localhost:80 111.104.224.189:4226 ESTABLISHEDtcp 0 0 localhost:80 111.60.222.163:51222 TIME_WAITtcp 0 1 localhost:80 211.105.223.92:50221 LAST_ACKtcp 0 0 localhost:80 111.109.224.111:42240 ESTABLISHEDtcp 0 0 localhost:80 111.106.22.85:50022 FIN_WAIT2tcp 0 0 :::22 :::* LISTEN
2、输出指定的列
tips:
①单引号中的被大括号括着的就是awk的语句,注意,其只能被单引号包含。
②$1..$n表示第几例。注:$0表示整个行,不指定具体的列默认对整个行进行处理。
如下例子输出第一列和第六列的数据
[root@sdw5 ~]# awk '{print $1,$6}' message.txt Proto Statetcp ESTABLISHEDtcp LISTENtcp LISTENtcp LISTENtcp TIME_WAITtcp FIN_WAIT2tcp ESTABLISHEDtcp ESTABLISHEDtcp FIN_WAIT2tcp ESTABLISHEDtcp TIME_WAITtcp ESTABLISHEDtcp 0tcp FIN_WAIT1tcp ESTABLISHEDtcp TIME_WAITtcp LAST_ACKtcp ESTABLISHEDtcp FIN_WAIT2tcp LISTEN
3、过滤条件1:输出第三列大于0的行
awk ' $3>0 {print $0}' message.txt
或者
awk ' $3>0' message.txt
[root@sdw5 ~]# awk ' $3>0 {print $0}' message.txt Proto Recv-Q Send-Q Local-Address Foreign-Address Statetcp 0 4166 localhost:80 61.148.242.38:30901 ESTABLISHEDtcp 0 4166 localhost:80 611.108.222.38:30221 ESTABLISHEDtcp 0 1 localhost:80 11 0 22 22tcp 0 1 localhost:80 111.102.221.209:22225 FIN_WAIT1tcp 0 1 localhost:80 211.105.223.92:50221 LAST_ACK
4、过滤条件2:第三列的值为0 && 第6列的值为LISTEN
awk '$3==0 && $6=="LISTEN" {print $0}' message.txt
[root@sdw5 ~]# awk '$3==0 && $6=="LISTEN" {print $0}' message.txt tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTENtcp 0 0 0.0.0.0:80 0.0.0.0:* LISTENtcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTENtcp 0 0 :::22 :::* LISTEN[root@sdw5 ~]#
5、awk的内建变量
$0 当前记录(这个变量中存放着整个行的内容)
$1~$n 当前记录的第n个字段,字段间由FS分隔
FS 输入字段分隔符 默认是空格或Tab
NF 当前记录中的字段个数,就是有多少列
NR 已经读出的记录数,就是行号,从1开始,如果有多个文件话,这个值也是不断累加中。
FNR 当前记录数,与NR不同的是,这个值会是各个文件自己的型号
RS 输入的记录分隔符, 默认为换行符
OFS 输出字段分隔符, 默认也是空格
ORS 输出的记录分隔符,默认为换行符
FILENAME 当前输入文件的名字
6、指定输入输出分隔符
其中:
FS指定输入文本每一行的分隔符为冒号:
OFS 指定每一列的值已 进行分隔输出
NR代表awk命令读取到的第几行文本
awk 'BEGIN{FS=":"} {print NR,$1,$6}' OFS="" /etc/passwd
[root@sdw5 ~]# awk 'BEGIN{FS=":"} {print NR,$1,$6}' OFS="" /etc/passwd 1 root /root2 bin /bin3 daemon /sbin4 adm /var/adm5 lp /var/spool/lpd6 sync /sbin7 shutdown /sbin8 halt /sbin9 mail /var/spool/mail10 operator /root11 games /usr/games12 ftp /var/ftp13 nobody /14 systemd-network /15 dbus /16 polkitd /17 sshd /var/empty/sshd18 postfix /var/spool/postfix19 mysql /var/lib/mysql
7、正则表达式例子:字符串匹配过滤
awk '$6 ~ /FIN/ || NR==1 {print NR,$1,$6}' OFS="" message.txt
[root@sdw5 ~]# awk '$6 ~ /FIN/ || NR==1 {print NR,$1,$6}' OFS="" message.txt 1 Proto State7 tcp FIN_WAIT210 tcp FIN_WAIT215 tcp FIN_WAIT120 tcp FIN_WAIT2
8、根据某一列的值进行文件拆分
根据第六列的值进行拆分,拆分后每个文件的内容,可以使用cat命令自行进行查看。
[root@sdw5 demo]# lltotal 4-rw-r--r--. 1 root root 1630 Dec 7 16:42 message.txt[root@sdw5 demo]# [root@sdw5 demo]# [root@sdw5 demo]# [root@sdw5 demo]# [root@sdw5 demo]# awk 'NR!=1 {print > $6}' message.txt [root@sdw5 demo]# [root@sdw5 demo]# [root@sdw5 demo]# [root@sdw5 demo]# lltotal 32-rw-r--r--. 1 root root 60 Dec 7 17:14 0-rw-r--r--. 1 root root 561 Dec 7 17:14 ESTABLISHED-rw-r--r--. 1 root root 78 Dec 7 17:14 FIN_WAIT1-rw-r--r--. 1 root root 231 Dec 7 17:14 FIN_WAIT2-rw-r--r--. 1 root root 77 Dec 7 17:14 LAST_ACK-rw-r--r--. 1 root root 312 Dec 7 17:14 LISTEN-rw-r--r--. 1 root root 1630 Dec 7 16:42 message.txt-rw-r--r--. 1 root root 234 Dec 7 17:14 TIME_WAIT[root@sdw5 demo]#
9、额外例子,重定向到指定的文件名(不按默认的列内容分组输出)
awk 'NR!=1 {if($6 ~ /ESTABLISHED/) print > "1.txt"; else if($6 ~ /FIN/) print > "2.txt"; else print > "3.txt" }' message.txt
执行完成后,可以看到多出来了1.txt,2.txt,3.txt三个文件,已根据第六列的内容,正则匹配不同的条件输出到 自定义的文件名的文本中。
这里已经可以看出来有点编程的味道了,大家都是程序猿就不多介绍了,逻辑很简单。
[root@sdw5 demo]# lltotal 32-rw-r--r--. 1 root root 60 Dec 7 17:14 0-rw-r--r--. 1 root root 561 Dec 7 17:14 ESTABLISHED-rw-r--r--. 1 root root 78 Dec 7 17:14 FIN_WAIT1-rw-r--r--. 1 root root 231 Dec 7 17:14 FIN_WAIT2-rw-r--r--. 1 root root 77 Dec 7 17:14 LAST_ACK-rw-r--r--. 1 root root 312 Dec 7 17:14 LISTEN-rw-r--r--. 1 root root 1630 Dec 7 16:42 message.txt-rw-r--r--. 1 root root 234 Dec 7 17:14 TIME_WAIT[root@sdw5 demo]# [root@sdw5 demo]# [root@sdw5 demo]# [root@sdw5 demo]# awk 'NR!=1 {if($6 ~ /ESTABLISHED/) print > "1.txt"; else if($6 ~ /FIN/) print > "2.txt"; else print > "3.txt" }' message.txt [root@sdw5 demo]# [root@sdw5 demo]# [root@sdw5 demo]# lltotal 44-rw-r--r--. 1 root root 60 Dec 7 17:14 0-rw-r--r--. 1 root root 561 Dec 7 17:18 1.txt-rw-r--r--. 1 root root 309 Dec 7 17:18 2.txt-rw-r--r--. 1 root root 683 Dec 7 17:18 3.txt-rw-r--r--. 1 root root 561 Dec 7 17:14 ESTABLISHED-rw-r--r--. 1 root root 78 Dec 7 17:14 FIN_WAIT1-rw-r--r--. 1 root root 231 Dec 7 17:14 FIN_WAIT2-rw-r--r--. 1 root root 77 Dec 7 17:14 LAST_ACK-rw-r--r--. 1 root root 312 Dec 7 17:14 LISTEN-rw-r--r--. 1 root root 1630 Dec 7 16:42 message.txt-rw-r--r--. 1 root root 234 Dec 7 17:14 TIME_WAIT
10、用于统计功能:统计当前目录下各个文件的大小总和
ls -ltr | awk '{sum+=$5} END {print sum}'
[root@sdw5 demo]# lltotal 44-rw-r--r--. 1 root root 60 Dec 7 17:14 0-rw-r--r--. 1 root root 561 Dec 7 17:18 1.txt-rw-r--r--. 1 root root 309 Dec 7 17:18 2.txt-rw-r--r--. 1 root root 683 Dec 7 17:18 3.txt-rw-r--r--. 1 root root 561 Dec 7 17:14 ESTABLISHED-rw-r--r--. 1 root root 78 Dec 7 17:14 FIN_WAIT1-rw-r--r--. 1 root root 231 Dec 7 17:14 FIN_WAIT2-rw-r--r--. 1 root root 77 Dec 7 17:14 LAST_ACK-rw-r--r--. 1 root root 312 Dec 7 17:14 LISTEN-rw-r--r--. 1 root root 1630 Dec 7 16:42 message.txt-rw-r--r--. 1 root root 234 Dec 7 17:14 TIME_WAIT[root@sdw5 demo]# [root@sdw5 demo]# ls -ltr | awk '{sum+=$5} END {print sum}'4736
11、统计进阶:根据第六列,统计每个值出现的次数
awk '{a[$6]++;} END{for (i in a) print i "," a[i];}' message.txt
前面看来if的逻辑判断语句,这里用到了for循环输出东西,其中利用到了数组,不懂的可以提出来。
[root@sdw5 demo]# awk '{a[$6]++;} END{for (i in a) print i "," a[i];}' message.txt LAST_ACK,1LISTEN,4State,1ESTABLISHED,7FIN_WAIT1,10,1FIN_WAIT2,3TIME_WAIT,3
12、BEGIN,END,{}总结介绍
END的意思是“处理完所有的行的标识”,即然说到了END就有必要介绍一下BEGIN,这两个关键字意味着执行前和执行后的意思,语法如下:
- BEGIN{ 这里面放的是执行前的语句 }
- END {这里面放的是处理完所有的行后要执行的语句 }
- {这里面放的是处理每一行时要执行的语句}
13、免费赠送中文高清版PDF
共享文件地址:https://pan.baidu.com/s/16EtS7Ip8HuOGFR-YhD3NdQ
如果需要提取码可以私信。
14、经典例子赠送
#打印99乘法表seq 9 | sed 'H;g' | awk -v RS='' '{for(i=1;i<=NF;i++)printf("%dx%d=%d%s", i, NR, i*NR, i==NR?"":"")}'#统计访问IP次数并排序取前10 awk '{a[$1]++}END{for(v in a)print v,a[v]|"sort -k2 -nr |head -10"}' access.log#按连接数查看客户端IPnetstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr