问题
本案例要求了解awk的流程控制操作,可自行设置awk语句来有验证以下操作:
if分支结构(双分支、多分支)
while/for循环结构
break、continue、next等其他控制语句
步骤
实现此案例需要按照如下步骤进行。
步骤一:awk过滤中的if分支结构
1)单分支
统计/etc/passwd文件中UID小于或等于500的用户个数:
[root@svr5 ~]# awk -F: 'BEGIN{i=0}{if($3<=500){i++}}END{print i}' /etc/passwd
39
统计/etc/passwd文件中UID大于500的用户个数:
[root@svr5 ~]# awk -F: 'BEGIN{i=0}{if($3>500){i++}}END{print i}' /etc/passwd
28
统计/etc/passwd文件中登录Shell是“/bin/bash”的用户个数:
[root@svr5 ~]# awk -F: 'BEGIN{i=0}{if($7~/bash$/){i++}}END{print i}'\
/etc/passwd
29
统计/etc/passwd文件中登录Shell不是“/bin/bash”的用户个数:
[root@svr5 ~]# awk -F: 'BEGIN{i=0}{if($7!~/bash$/){i++}}END{print i}'\
/etc/passwd
38
2)双分支
分别统计/etc/passwd文件中UID小于或等于500、UID大于500的用户个数:
[root@svr5 ~]# awk -F: 'BEGIN{i=0;j=0}{if($3<=500){i++}else{j++}}END{print i,j}' /etc/passwd
39 28
分别统计/etc/passwd文件中登录Shell是“/bin/bash”、 登录Shell不是“/bin/bash”的用户个数:
[root@svr5 ~]# awk -F: 'BEGIN{i=0;j=0}{if($7~/bash$/){i++}else{j++}}\
END{print i,j}' /etc/passwd
29 38
3)多分支
分别统计/etc/passwd文件中登录Shell是“/bin/bash”、“/sbin/nologin”、其他的用户个数:
[root@svr5 ~]# awk -F: 'BEGIN{i=0;j=0;k=0}{if($7~/bash$/){i++}\
else if($7~/nologin$/){j++}else{k++}}END{print i,j,k}' /etc/passwd
29 33 5
步骤二:awk过滤中的while/for循环结构
1)while循环
统计/etc/passwd文件内“root”出现的次数。
—— 分析:以“:”或“/”做分隔,针对每一行的每一列进行比对,如果包含“root”,则次数加1。其中,逐行处理直接由awk完成,逐列处理交给while循环,通过i变量依次取$1、 2 、 … … 、 2、……、 2、……、NF进行检查;变量j在预处理时赋值0,没匹配一个字段加1。
[root@svr5 ~]# awk -F [:/] \
'BEGIN{j=0}\
{i=1}{while(i<=NF){if($i~/root/){j++};i++}}\
END{print j}' /etc/passwd
4
此例仅为说明while循环的用法。
实际应用时,上述操作可以简单处理,可通过命令替换将文件内容赋值给一个变量(变为一行文本),然后针对此变量值以目标字符串“root”作为分隔,获取总字段数-1即可得目标字符串的总数量:
[root@svr5 ~]# echo $(cat /etc/passwd) | awk -F "root" '{print NF-1}'
4
2)for循环
类似于Shell中C风格的for循环,基本格式如下:
for(初值;条件;步长){编辑指令}
比如,输出从1~10之间的整数:
[root@svr5 ~]# awk 'BEGIN{for(i=1;i<=10;i++){print i}}'
1
2
3
4
5
6
7
8
9
10
输出从1~20之间所有的3的倍数:
[root@svr5 ~]# awk 'BEGIN{for(i=1;i<=20;i++){if(i%3==0){print i}}}'
3
6
9
12
15
18
计算从1~100内各整数的总和:
[root@svr5 ~]# awk 'BEGIN{for(i=1;i<=100;i++){sum+=i;\
if(i==100){print sum}}}'
5050
步骤三:awk过滤中的其他控制结构
以/etc/rc.local文件为例,确认文件内容如下:
[root@svr5 ~]# cat /etc/rc.local
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.
touch /var/lock/subsys/local
使用next可跳过当前行。比如,输出文件中超过2个字段(默认分隔)的行:
[root@svr5 ~]# awk 'NF<=2{next}{print}' /etc/rc.local
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.
上述操作的效果等同于:
[root@svr5 ~]# awk 'NF>2{print}' /etc/rc.local
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.