1. awk 使用进阶
1.1. 格式化输出 print 和 printf
-
print
函数 类似echo
# chen @ localhost in ~/Shell [18:25:12] $ date | awk '{print "Month: "$2 "\nYear: " $1}' Month: 12月 Year: 2019年
-
printf
函数# chen @ localhost in ~/Shell [18:31:51] $ awk 'BEGIN{FS=":"};{printf "%-15s %-15s %-15s\n",$1,$6,$NF}' passwd root /root /bin/zshi in /bin /sbin/nologin ddaemon /sbin /sbin/nologin adm /var/adm /sbin/nologin sync /sbin /bin/sync shutdown /sbin /sbin/shutdown
- %s 字符类型
- %d 数值类型
- 15:占15个字符
- “-” 表示左对齐,默认是右对齐
- printf 默认不会在行尾自动换行,加
\n
1.2. 定义变量
# chen @ localhost in ~/Shell [18:36:13]
$ awk -v NUM=3 -F: '{print NUM}' passwd
3
3
3
3
3
3
# 注意:awk中调用定义的变量不需要加$
# chen @ localhost in ~/Shell [18:37:04]
$ awk -v NUM=3 -F: '{print $NUM}' passwd
0
1
2
3
5
6
1.3. BEGIN…END 使用
1.3.1. 概述
BEGIN
:表示在程序开始前开始执行END
:表示所有文件处理完后执行- 用法:
' BEGIN {开始处理前}; {处理中}; END{处理结束后}'
1.3.2. 学习示例
-
打印登录 shell 和 家目录
# chen @ localhost in ~/Shell [19:07:33] $ awk 'BEGIN {FS=":";print "Login shell\t\tLogin_home\n"};{ printf "%-25s %-25s\n", $1,$NF}; END{ print "****************************************"}' passwd Login shell Login_home root /bin/zshi in /sbin/nologin ddaemon /sbin/nologin adm /sbin/nologin sync /bin/sync shutdown /sbin/shutdown ****************************************
2. awk 和正则的综合使用
- == 等于
- != 不等于
- > 大于
- < 小于
- \~ 匹配
2.1. 学习示例
2.1.1. 打印以 root 开头或者以 adm 开头的行
# chen @ localhost in ~/Shell [19:25:20] C:130
$ awk '/^adm/ || /^root/ {print $0}' passwd
root:x:0:0:root:/root:/bin/zshi
adm:x:3:4:adm:/var/adm:/sbin/nologin
# 方法2
# chen @ localhost in ~/Shell [19:25:23]
$ awk '/^adm/;/^root/ {print $0}' passwd
2.1.2. 打印1到7行 以 bash 结尾的内容
# chen @ localhost in ~/Shell [19:30:14]
$ awk 'NR>=2 && NR<=7 && $0 ~ /login$/{print $0}' passwd
in:x:1:1:bin:/bin:/sbin/nologin
ddaemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
# 方法2
# chen @ localhost in ~/Shell [19:30:19]
$ awk 'NR>=2 && NR<=7 && /login$/{print $0}' passwd
in:x:1:1:bin:/bin:/sbin/nologin
ddaemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
2.1.3. 获取电脑的 ip
# chen @ localhost in ~/Shell [19:34:07]
$ ifconfig eth0 | grep broadcast
inet 192.168.10.36 netmask 255.255.255.0 broadcast 192.168.10.255
# chen @ localhost in ~/Shell [19:38:03]
$ ifconfig eth0 | grep broadcast | awk -F'[ ]+' '{print $3}'
192.168.10.36
# 方法2
# chen @ localhost in ~/Shell [19:40:35]
$ ifconfig eth0 | awk -F'[ ]+' '/broadcast/{print $3}'
192.168.10.36
# 方法3
# chen @ localhost in ~/Shell [19:41:36]
$ ifconfig eth0 | awk -F'[ ]+' '/broadcast/{print $3RS$5RS$7}'
192.168.10.36
255.255.255.0
192.168.10.255
3. awk 条件判断
3.1. if结构
3.1.1. 语法结构
awk [选项] '正则','地址定位 {awk语句}' 文件名
3.1.2. 学习案例
# chen @ localhost in ~/Shell [19:47:31]
$ awk -F: '{if ($3>=1 && $3<=5) {print $1,$3}}' passwd
in 1
ddaemon 2
adm 3
sync 5
3.2. if…else
3.2.1. 语法结构
awk [选项] '正则','地址定位 {awk语句}' 文件名
{ if (表达式) {语句;语句;...} else {语句;语句;...} }
3.2.2. 学习案例
判断用户是否为普通用户
# chen @ localhost in ~/Shell [21:42:30]
$ awk -F: '{ if($3>=500 && $3!=65534) {print "普通用户"} else { print "不是普通用户"} }' passwd
不是普通用户
不是普通用户
不是普通用户
不是普通用户
不是普通用户
不是普通用户
3.3. if else if {} else if{}
3.3.1. 语法结构
awk [选项] '正则','地址定位 {awk语句}' 文件名
{ if (表达式) {语句;语句;...} else if (表达式2){语句;语句;...} else if (表达式2) {语句;语句...} ... else {语句;语句...} }
3.3.2. 学习案例
计算系统中管理员、系统用户、普通用户个数
# chen @ localhost in ~/Shell [21:54:20]
$ awk -F: '{ if( $3==0 ) {i++} else if($3>=1 && $3<=499 || $3==65534) {j++} else {k++} }; END {print "管理员个数为: " i "\n系统用户个数为: "j "\n普通用户个数为: "k} ' passwd2
管理员个数为: 1
系统用户个数为: 4
普通用户个数为: 3
4. awk 循环结构
4.1. for结构
4.1.1. 语法结构
awk [选项] '正则','地址定位 {awk语句}'
{ for (表达式) {语句;语句;... } }
4.1.2. 学习案例
-
打印1-10中的奇数
# chen @ localhost in ~/Shell [9:56:49] C:1 $ awk 'BEGIN { for(i=1;i<=10;i+=2) { print i } }' 1 3 5 7 9
-
计算1-5的和
# chen @ localhost in ~/Shell [10:01:10] C:1 $ awk 'BEGIN { sum=0; for(i=1;i<=5;i++) sum=sum+i; print sum }' 15 # 方法2 # chen @ localhost in ~/Shell [10:05:09] $ for (( i=1;i<=5;i++ ));do echo $i; done | awk '{sum+=$0}; END {print sum }' 15
4.2. while结构
4.2.1. 语法结构
awk [选项] '正则','地址定位 {awk语句}'
{ while (表达式) {语句;语句;... } }
4.2.2. 学习案例
-
打印1-10中的奇数
# chen @ localhost in ~/Shell [10:10:12] $ awk 'BEGIN {i=1;sum=0; while(i<=5) {print i;i++}}' 1 2 3 4 5
-
计算1-5的和
# chen @ localhost in ~/Shell [10:05:27] $ awk 'BEGIN { i=0;sum=0; while(i<=5) {sum=sum+i;i++} print sum }' 15
4.3. 嵌套循环
学习案例
利用嵌套循环打印如下所示图形
5
54
543
5432
54321
# chen @ localhost in ~ [10:16:54]
$ awk 'BEGIN { for (y=1;y<=5;y++){ for(x=1;x<=y;x++) {printf 6-x} print} }'
5
54
543
5432
54321
5. awk 统计案例
5.1. 统计系统中各种类型的 shell
# chen @ localhost in ~ [10:21:46] C:130
$ awk -F: '{shells[$NF]++}; END{ for(i in shells) {print i,shells[i] } }' /etc/passwd
/bin/sync 1
/sbin/nologin 43
/sbin/halt 1
/bin/zsh 2
/sbin/shutdown 1
5.2. 统计网站访问状态
# chen @ localhost in ~ [10:29:09]
$ ss -an | grep :80 | awk '{ states[$2]++ };END {for(i in states) { print i, states[i]}}' | sort -k2 -rn
ESTAB 18
TIME-WAIT 13
LISTEN 10
5.3. 统计网站的每个 IP 的数量
# chen @ localhost in ~ [10:53:05]
$ netstat -ant | grep :80 | awk -F ':' '{print $2}' | awk -F '[ ]+' '{ip_count[$2]++}; END {for (i in ip_count) {print "ip: "i" |count: "ip_count[i]} }'
ip: 192.168.10.100 |count: 3
ip: 192.168.10.96 |count: 20
ip: 192.168.10.102 |count: 2
ip: 192.168.10.98 |count: 2
ip: 0.0.0.0 |count: 10
ip: 192.168.10.104 |count: 2
ip: 192.168.10.108 |count: 1
5.4. 统计 tomcat 网站日志中 PV 量
# chen @ localhost in /usr/local/tomcat/apache-tomcat-8.5.42/logs [10:57:50]
$ awk -F'[ ]+' '{pv[$1]++}; END{for (i in pv) {print i, pv[i]}}' localhost_access_log.2019-09-11.txt
192.168.10.71 3
192.168.10.36 9