awk实例讲解说明
# 提示:awk读取文件内容的每一行时,将对比改行是否与给定的模式相匹配,如果匹配则执行处理过程,否则对该行不做任何处理。 如果没有指定处理脚本,则把匹配的行显示到标准输出,即默认处理动作是print打印行; 如果没有指定模式匹配,则默认匹配所有数据。 |
-
passwd文件内容如下 [root@null ~]# cat passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
-
例1:FS变量 [root@null ~]# awk -F:'{print $1,$3}' passwd #-F指定分隔符: 显示如下 root 0 bin 1 daemon 2 adm 3 lp 4 [root@null ~]# awk -v FS=":"'{print $1,$3}' passwd #-v 指定变量的FS分隔符 root 0 bin 1 daemon 2 adm 3 lp 4
-
例2:RS变量 [root@null ~]# awk -v RS=":"'{print $1,$3}' passwd #指定换行符为:,文件一遇到:就换行 root x 0 0 root /root /bin/bash ....# 以下省略
-
例3:OFS变量 [root@null ~]# awk '{print $1,$3}' passwd #默认输出分隔符为空格字符 root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin [root@null ~]# awk -F:-v OFS="============"'{print $1,$3}' passwd #指定输出分隔符为============ root============0 bin============1 daemon============2 adm============3 lp============4
-
例4:ORS变量 [root@null ~]# awk -F:-v ORS="--"'{print $1,$3}' passwd #指定换行符为 -- 当然也可以为空 root 0--bin 1--daemon 2--adm 3--lp 4--[root@null ~]# [root@null ~]# awk -F:-v ORS="--"'{print $1,$3}' passwd #指定换行符为空的时候 root 0--bin 1--daemon 2--adm 3--lp 4--[root@null ~]#
-
例5:NF、NR、FNR、FILENAME的值 [root@null ~]# awk -F:'{print NF }' passwd #变量NF,当前行的字段数。在awk里变量引用不需要加$ 7 7 7 7 7
-
例6:ARGC、ARGV的值 [root@null ~]# awk '{print ARGC }' passwd # ARGC命令行的参数的个数,注意:命令awk也算是一个参数 2 2 2 2 2 [root@null ~]# awk '{print ARGV[0] }' passwd # 数组,保存了命令行参数;[]显示命令行第几个参数 awk awk awk awk awk [root@null ~]# awk '{print ARGV[1]}' passwd passwd passwd passwd passwd passwd
-
例7:自定义变量(变量名需要区分字符大小写) [root@null ~]# awk '{file="passwd";print file,$1}' passwd #定义file值为passwd,并打印file变量,和$1的值 passwd root:x:0:0:root:/root:/bin/bash passwd bin:x:1:1:bin:/bin:/sbin/nologin passwd daemon:x:2:2:daemon:/sbin:/sbin/nologin passwd adm:x:3:4:adm:/var/adm:/sbin/nologin passwd lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
3、printf命令
格式:printf format,item1,item2,...
要点:
1、format(格式)是必须的;
2、不会自动换行,需显示给定行分隔符;
3、format中需要分别为后面的每个item指定一个格式符;
格式符:都以%开头,后跟一个字符
%c:显示字符的ASCII码;
%d,%i:显示十进制整数;
%e,%E:科学计数法显示数值
%f:显示为浮点数
%g,%G:以科学计数法格式或浮点数格式显示数值;
%s:字符串
%u:无符号的整数
%%:显示%自身
修饰符:
#[.#]:第一个#指定显示宽度,第二个#表示小数点后的精度;(#用数字替代)
-:左对其
+:显示数值符号
-
例1:格式符 [root@null ~]# awk 'BEGIN{printf "%c","a"}'#%c显示ASCII码,但这里显示的是字符本身,换成数字就明显了,无法复制出来 a[root@null ~]# [root@null ~]# awk 'BEGIN{printf "%d",6}'#显示为十进制整数,字母都会以数值0表示,浮点数也会四舍五入变成整数 6[root@null ~]# [root@null ~]# awk 'BEGIN{printf "%f\n",6.0001}'#要显示小数点后的数值需用到%f,\n是换行符,只小数点前后小数点后加起来8个不足用0表示(小数点在这里也算一个字符) 6.000100 [root@null ~]# awk 'BEGIN{printf "%e\n",600013.24165431}'#%e,%E:科学计数法显示数值 6.000132e+05 [root@null ~]# awk 'BEGIN{printf "%g\n",600013111111.24165431}'#%g,%G:以科学计数法格式或浮点数格式显示数值; 6.00013e+11
-
例2:修饰符 [root@null ~]# awk 'BEGIN{printf "%30s\n","abcd"}' abcd #在字符前隔着30个字符 [root@null ~]# awk 'BEGIN{printf "%-30s\n","abcd"}'# -代表左对其 abcd [root@null ~]# awk -F:'{printf "%20s:%5s\n",$1,$3}' passwd # $1显示30个字符,$3显示5个字符 root:0 bin:1 daemon:2 adm:3 lp:4 [root@null ~]# awk 'BEGIN{printf "%40.9f\n",45678947.1534564654}'#第一个#指定显示宽度,第二个#表示小数点后的精度(小数点后面是9个字符宽度);(#用数字替代) 45678947.153456464
4、操作符
算术操作符:
+,-,*,/,^,%
-x:负值
+x:转换为数值
字符串操作:字符串连接
赋值操作符:
=,+=,-=,*=,/=,^=,%=
++,--
比较操作符:
>,>=,<,<=,==,!=
模式匹配符:
~
!~
逻辑操作符:
&&
||
条件表达式:
selector?if-true-expression:if-false-expression
函数调用:
function_name(argu1,argu2)
-
例1:条件表达式 [root@null ~]# awk -F:'{$3>=1?usertype="system user":usertype="root user";printf "%20s:%-s\n",$1,usertype}' passwd #判断变量$3是否大于或等于1,大于或等于1的话,usertype的值就等于system user,否者就等于root user,打印$1的距离为20s,usertype的值左对其$1,并且换行,然后显示$1和变量usertype root:root user bin:system user daemon:system user adm:system user lp:system user
5、PATTERN
1、/regular expression/:仅处理能够被/regular expression/所匹配到的行;
2、relational expression:关系表达式,有真假之分,一般来说,其结果为非0或为非空字符串时为"真",否则,为"假";
3、line ranges:行范围,类似sed或vim的地址定界法; startline,endline
4、BEGIN/END:特殊模式
仅在awk运行程序之前执行一次(BEGIN)或仅在awk运行程序之后执行一次(END);
5、empty:空模式,匹配任意行;
-
[root@null ~]# awk -F:'/^\<root\>/{print $0}' passwd #仅处理能够被/regular expression/所匹配到的行; root:x:0:0:root:/root:/bin/bash [root@null ~]# awk -F:'$3>=1{print $0}' passwd #打印出所有$3大于或等于1的条目,关系表达式 bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin [root@null ~]# awk -F:'$5~/root/{print $0}' passwd #匹配$5中有root字段的条目,模式匹配符 root:x:0:0:root:/root:/bin/bash [root@null ~]# awk -F:'$7~/bash\>/{print $0}' passwd #匹配$7以bash结尾的条目,模式匹配符 root:x:0:0:root:/root:/bin/bash [root@null ~]# awk -F:'BEGIN{print "username shell"}{print $1,$7}' passwd #在处理之前由BEGIN处理一段username shell添加在前面,然后处理后续部分 username shell root /bin/bash bin /sbin/nologin daemon /sbin/nologin adm /sbin/nologin lp /sbin/nologin [root@null ~]# awk -F:'BEGIN{print "username shell\n-----------------"}{print $1,$7}END{print "----------------\nEND"}' passwd #BEGIN与END username shell ----------------- root /bin/bash bin /sbin/nologin daemon /sbin/nologin adm /sbin/nologin lp /sbin/nologin ----------------- END
6、控制语句
if (condition) statement [ else statement ]
while (condition) statement
do statement while (condition)
for (expr1; expr2; expr3) statement
for (var in array) statement
break
continue
delete array[index]
delete array
exit [ expression ]
{ statements }
6.1 if-else
语法:if (condition) statement [ else statement ]
if (condition) { statement; } [ else { statement; }]
用法:对awk取得的整行或行中的字段做条件判断;
-
[root@null ~]# awk -F:'{if ($3>=1) {print $1,"is a system user."} else {print $1 " is a root user."}}' passwd # if判断$3是否大于或等于1,如果条件满足就显示 $1,"is a system user.",如果条件不满足就显示$1 " is a root user. root is a root user. bin is a system user. daemon is a system user. adm is a system user. lp is a system user.
6.2 while循环
语法:while (condition) statement
while (condition) { statements }
条件为真时进行循环,直到为假退出;
用法:通常用于在当前行的各字段间进行循环;
-
用while循环判断每个单词出现的个数 [root@null ~]# awk -F:'{i=1;while(i<=NF){printf "%20s:%d\n",$i,length($i); i++}}' passwd root:4 x:1 0:1 0:1 root:4 /root:5 .......
6.3 do-while循环
语法:do statement while (condition)
do { do-while-body } while (condition)
意义:至少执行一次循环体;
6.4 for循环
语法:for (expr1;expr2;expr3) statement
for (expr1;expr2;expr3) { statement }
for (varaiable assignment; condition; iteration process) { for-body }
for循环在awk中有一个专用于遍历数组元素;
语法:for (var in array) { for-body }
-
用for循环判断每个单词出现的个数 [root@null ~]# awk -F:'{for(i=1;i<=NF;i++) {printf "%s:%d\n", $i,length($i)}}' passwd root:4 x:1 0:1 0:1 root:4 /root:5 /bin/bash:9
6.5 switch
语法:switch (expression) {case VALUE or /REGEXP/:statement; ...; default; statementN}
6.6 break and continue
break [n]:退出当前循环
continue:提前结束本轮循环,直接进入下轮循环
6.7 next
提前结束对本行的处理而进入下一行的处理
-
[root@null ~]# awk -F:'{if($3%2!=0) next; print $1,$3}' passwd #if判断$3的值对2取模,等于0就进入下一轮就是打印出来,不复合就不让进入下一行 root 0 daemon 2 lp 4
7、Array(数组)
关联数组:array[index-expression] (数组[索引表达式])
index-expression:
可以使用任意字符串;
如果某数组元素事先不存在,在引用时,awk会自动创建此元素并将其值初始化为空串;
因此,若要判断数组是否存在某元素,要使用"index in array(索引阵列)" 进行;
a1[mon]="Monday"
print a1[mon]
要遍历数组中的每个元素,使用:for(var in array) { for body }
注意:var会遍历array的每一个索引,print array[var]
-
[root@null ~]# cat awk.txt #awk.txt文件中的内容 how are you ? how do you do? what are you doing? [root@null ~]# awk '/^how/{for(i=1;i<=NF;i++) {count[$i]++}}END{for(j in count) {print j,count[j]}}' awk.txt 显示每个单词出现的次数 are 1 do2 how 2 ?2 you 2
8、函数
8.1 内置函数
数值处理:
rand():返回0和1之间的随机数
字符串处理:
length([s]):返回指定字符串的长度
sub(r,s [,t]):以r所表示的模式来查找t字符串中的匹配,将其第一次出现替换同s所表示的字符串;
gsub(r,s [,t]):以r所表示的模式来查找t字符串中的匹配,将其所有的出现均替换同s所表示的字符串;
split(s,a [, r]):以r为分隔符切割字符串s,并将切割的结果保存至a表示数组中;
substr(s,i [,n]):从s表示的字符串中取字串,从i开始,取n个字符;
时间类的函数:
systime():取时间戳
位运算函数:
and(v1,va2);
8.2 自定义函数:
function f_name(p,q)
{
...
}
-
统计当前连接状态 [root@null ~]# netstat -tan | awk '/^tcp/{len=split($5,client,":");ip[client[len-1]]++}END{for(i in ip){print i,ip[i]}}' 7 172.16.34.2342 0.0.0.07