awk详细案例分析
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了awk详细案例分析相关的知识,希望对你有一定的参考价值。
awk:报告生成器格式化后显示信息
语法:
awk [options] ‘script‘ file1 file2, ...
awk [options] ‘PARTTERN action ‘ file1 file2, ...
最常见的action:print,printf
awk的基本特征:
a.每一次取一行
b.根据指定的分隔符(不指定是位空白字符)将该行切割位列,使用$0(整行),$1,$2,$3...(第一列,第二列,...)
c.可以指定行号,列号,切割符,操作后分隔符
案例:
chkconfig --list |grep 3:启用 |awk ‘print $1‘
tail -1 /etc/passwd |awk -F ‘:‘ ‘BEGINOFS="---"print $1,$6,$7‘ ##OFS指定输出分隔符
ifconfig eth1 |awk -F ‘[ :]+‘ ‘NR==2 print $4‘
ifconfig eth1 |awk -F ‘[ :]+‘ ‘NR==2 print "eth1_ip="$4‘ ##可以加入显示内容
awk ‘BEGIN print "line one \nline two\nline three"‘
4.高级awk的使用:
1)awk变量:
FS:列分隔符,默认位空白
RS:行分隔符,默认位换行符
OFS:输出列分隔符
ORS :输出行分隔符
2)awk内置变量
NR:处理中行数
FNR:单个文件的行数
NF:列的个数
案例:
ifconfig eth1 |awk ‘print NR‘
ifconfig eth1 |awk ‘print NF‘
3)自定义变量:
awk ‘BEGINtest="www.linuxfan.cn";print test‘
awk -v test="linuxfan.cn" ‘BEGINprint test‘
4)printf
使用的格式:
printf format, item1,item2, ...
特征:
a.必须指定format,用于指定后面item的输出格式
b.printf语句不会自动打印换行符:\n
c.format格式以%+一个字符,如下:
%c:显示字符的ASCII码
%d,%i:十进制整数
%e:科学计数法显示数值
%f:显示浮点数(小数)
%s:显示字符串
%u:无符号整数
%%:显示%
d.修饰符:N:显示宽度,-:左对齐,+:显示数值符号,如%-c(左对齐)
案例:
chkconfig --list |grep 3:启用 |awk ‘printf "%-10s",$1‘ ##在统一行显示
awk -F : ‘printf "%-15s %-10d %-10s\n",$1,$3,$7‘ /etc/passwd
5)awk的操作符
a.算数操作符
-x
+x
x^y
x*y
xy
x/y
x+y
x-y
x%y
b.赋值操作符
+=
-=
*=
/=
%=
++
c.布尔值
awk中,任何非0值或者非空字符串都为真,反之为假
d.比较操作符:>,<,>=,<=,==,!=,~,!~(x ~ y,字符串能被表达式y匹配)
d.逻辑操作符:&&,||,!
e.条件表达式:条件?if-true-exp:if-false-exp
f.调用函数:function_name (pa1, pa2)
6)awk常见的模式类型:
a.正则表达式(regexp),格式为:/regular expression/
awk -F : ‘/^u/print $1‘ /etc/passwd
b.表达式(expression),值位非0或位非空是满足条件,如$1 ~ /foo/或 $1 == "root"
awk -F : ‘$3>=500print $1,$3,$7‘ /etc/passwd
awk -F : ‘$3+1<=100&&$3+1>=10print $1,$3,$7‘ /etc/passwd
awk -F : ‘$2=="!!"print $1,$2‘ /etc/shadow ##检查未初始化密码的用户
passwd -d u01
awk -F : ‘$2==""print $1‘ /etc/shadow ##打印密码为空的用户
awk -F : ‘$7~"bash$"print $1,$3,$7‘ /etc/passwd ##匹配$7为bash结束行
awk -F : ‘$7!~"bash$"print $1,$3,$7‘ /etc/passwd
c.匹配范围(ranges),指定的匹配范围,格式为part1,part2
awk -F : ‘$3==3,$3==10print $1,$3,$7‘ /etc/passwd
awk -F : ‘$1=="root",$1=="adm"print $1,$3,$7‘ /etc/passwd
awk -F : ‘/^r/,/^a/print $1,$3,$7‘ /etc/passwd
d.特殊模式(BEGIN/END)
awk -F : ‘BEGINprintf "%-10s%-10s%-20s\n","UserName","ID","Shell"printf "%-10s%-10s%-20s\n",$1,$3,$7‘ /etc/passwd ##在awk处理之前打印头部BEGIN
awk -F : ‘BEGINprintf "%-10s%-10s%-20s\n","UserName","ID","Shell"$7~"bash$"printf "%-10s%-10s%-20s\n",$1,$3,$7‘ /etc/passwd ##多个模式混合使用
awk -F : ‘BEGINprintf "%-10s%-10s%-20s\n","UserName","ID","Shell"$7~"bash$"printf "%-10s%-10s%-20s\n",$1,$3,$7ENDprint "End of report"‘ /etc/passwd ##在awk执行完成后打印尾部END
awk -v i=1 ‘$5~"yum"i++ENDprint "yum use times:", i‘ /var/log/messages
/正则表达式/:使用通配符的扩展集合。
关系表达式:如字符串或数字的比较。
模式匹配表达式:模式(指定一个行的范围,不包含BEGIN,END)
7)常见的action:
expressions:表达式
control satatements:控制语句
compound statements:混合语句
input statements:输入语句
output statements:输出语句
8)action中的控制语句:
a.if-else
语法:if (condition) command action1; else command action2
案例:
awk -F : ‘$7~"bash"if ($1=="root") print $1, "admin";else print $1, "Common User"‘ /etc/passwd
awk -F : -v sum=0 ‘if ($3>=500) sum++ENDprint sum‘ /etc/passwd
awk -F : -v sum=0 ‘$7~"bash"if ($1=="root") print $1, "admin" sum++;else print $1, "Common User" sum++ENDprint "can login user num:",sum‘ /etc/passwd ##二合一
awk -F : ‘$7~"bash$"if ($1=="root") printf "%-15s: %s\n",$1,"admin";else printf "%-15s: %s\n",$1,"common user"‘ /etc/passwd ##格式化输出
b.while循环:循环字段,awk本身就是行的循环
语法:while (condition)statement1;statement2;...
案例:
awk -F: ‘i=1;while (i<=3) print $i;i++‘ /etc/passwd ##循环打印前3列
awk -F : ‘i=1;while (i<NF) if (length($i)<=4) print $i;i++‘ /etc/passwd ##循环整行,并打印出长度小于4的字段列
c.do-while
语法:do statement1;statement2;... while (condition)
awk -F : ‘i=1;do print $i;i++while(i<=3)‘ /etc/passwd
d.for
语法:for (variable assignment;condition;iteration process)statement1, statement2,...
案例:
awk -F : ‘for(i=1;i<=3;i++) print $i‘ /etc/passwd
for循环遍历数组元素:
语法:for (i in array) statement1, statement2,...
案例:
awk -F : ‘SH[$NF]++;ENDfor (i in SH)print i,SH[i]‘ /etc/passwd
netstat -ant |awk ‘/^tcp/++S[$NF]ENDfor(a in S) print a, S[a]‘
awk ‘counts[$1]++ENDfor (url in counts) print url,"access times:",counts[url]‘ /var/log/httpd/access_log
awk ‘S[$5]++ENDfor (i in S) print i,S[i]‘ /var/log/messages
awk ‘AH[$1]++ENDfor (i in AH) printf "%-20s:%s\n", i, AH[i]‘ /var/log/httpd/access_log
9).awk中的数组
array[index-expression]
index-expression可以使用任意字符串;需要注意的是,如果某数据组元素事先不存在,那么在引用其时,awk会自动创建此元素并初始化为空串;因此,要判断某数据组中是否存在某元素,需要使用index in array的方式。要遍历数组中的每一个元素,需要使用如下的特殊结构:
for (var in array) statement1, ...
例如:
state[abc]=3
state[efg]=6
for (A in state) print A,state[A] ##A一定是index-expression(下标abc/efg),state[A]是一个具体的值(3/6)
[[email protected] ~]# netstat -ant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:22 0.0.0.0: LISTEN
tcp 0 0 127.0.0.1:25 0.0.0.0: LISTEN
tcp 0 0 192.168.1.106:22 192.168.1.101:36318 ESTABLISHED
以上命令显示的结果中,每一行最后一个字段为状态,若要统计每种状态的个数,只需要将state作为数组下标,由于awk本身就是一个行的循环,所以只需要给数字自加1(++)即可实现统计,具体操作如下:
netstat -ant |awk ‘S[$6]++ENDfor(i in S)print i,S[i]‘
10)awk的内置函数
split(string,array[filedsep[,seps]])
作用:将string表示的字符串以fieldsep为分隔符进行分隔,并将分隔后的结果保存至array为名的数组中;数组下标为从0开始的序列;
netstat -ant | awk ‘/:80\>/split($5,clients,":");IP[clients[1]]++ENDfor(i in IP)print IP[i],i‘ | sort -rn | head -50
length([string])
功能:返回string字符串中字符的个数;
substr(string, start [, length])
功能:取string字符串中的子串,从start开始,取length个;start从1开始计数;
system(command)
功能:执行系统command并将结果返回至awk命令
systime()
功能:取系统当前时间
tolower(s)
功能:将s中的所有字母转为小写
toupper(s)
功能:将s中的所有字母转为大写
以上是关于awk详细案例分析的主要内容,如果未能解决你的问题,请参考以下文章
自动化运维必须要学的Shell文本处理三剑客之——awk用法(超多案例详细介绍)