一. AWK
1.awk必备基本概念
a. $0,$1,$2概念
$0在没有指定区域或分隔符的情况下默认输出文件里的所有内容;
如果指定了区域,比如像下面这样,那么会输出区域的某几行。
$1和$2是指输出被FS字段分隔符分隔之后的第一列和第一列数据
[root@localhost ~]# awk 'NR==1{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# awk 'NR==2{print $0}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
b.NF,NR,FS,RS
FS:字段分隔符,可以用-F来指定字段分隔符;默认是空格
RS:记录分隔符,默认是每行末尾的换行符\n,可以统计行数
NF:区域号,一般不用于指定第几列。$NF指的是最后一列,可与print联合使用
NR:行号,可以指定行号取数据,同时可以统计文件里的总共行数
[root@localhost ~]# awk -F ":" '{print "username:"$1"\t\tuid:"$3}' /etc/passwd|head -2
username:root uid:0
username:bin uid:1
\t是空格的意思
题目1:要求输出/etc/passwd文件里的倒数第二行数据
[root@localhost ~]# awk 'END{print NR}' /etc/passwd
47
先利用END模块取出所有行,再指定倒数第二行的行数。
题目2:要求将一些被换行符分隔的字段输出为一行
[root@localhost jizuo]# vim awk/test-1.txt
mmy the Weasel
100 Pleasant Drive
San Francisco, CA 12345
Big Tony
200 Incognito Ave.
Suburbia, WA 67890
[root@localhost jizuo]# awk 'BEGIN{FS="\n";RS=""}{print $1","$2","$3}' awk/test-1.txt
mmy the Weasel,100 Pleasant Drive,San Francisco, CA 12345
Big Tony,200 Incognito Ave.,Suburbia, WA 67890
所用方法是将行分隔符(RS)由换行符改为空或空行;将FS(字段分隔符)由默认的空格改为换行符。
此种方法也有局限,就是只能输出指定字段的文件成一行;如果是无限行数据呢,可以采用下面的方法:
root@localhost jizuo]# awk 'BEGIN{RS="EOF"}{gsub(/\n/,",");print}' awk/test-1.txt
mmy the Weasel,100 Pleasant Drive,San Francisco CA 12345,Big Tony,200 Incognito Ave.,Suburbia WA 67890,
先将行分隔符改为"EOF",文件末尾的意思。然后利用gsub函数将换行符改为逗号,然后输出
c. print模块
在代码块中,只能有一个print命令。并且,如果只出现了print命令,那么将默认打印整行。
以下的两个例子中可以看到,不论echo的是什么内容,awk依然输出的是print的内容。包括第二个例子输出了与/etc/passwd同样行的hiya内容
[root@localhost ~]# echo hhh|awk '{print "hello world"}'
hello world
[root@localhost ~]# awk '{print "hiya"}' /etc/passwd
hiya
hiya
hiya
hiya
hiya
hiya
hiya
...
d.BEGIN和END模块
BEGIN模块是在处理所有的文本信息之前执行的代码块,主要用于初始化FS变量及其他全局变量。
END模块是在处理完文件中的所有行之后执行的代码块,主要用于执行最终计算和打印输出结尾流的摘要信息。
e.运算符
算数运算符,逻辑运算符,关系运算符
[root@localhost ~]# awk 'BEGIN{a=5;a+=5;print a}'
10
[root@localhost ~]# awk 'BEGIN{a=1;b=2;print (a>2&&b>1,a>1||b>1)}'
0 1
[root@localhost ~]# echo|awk 'BEGIN{a="100testaaa"}a~/100/{print "ok"}'
ok
[root@localhost ~]# awk 'BEGIN{a="100testaaa";if(a~/100/){print"ok"}}'
ok
2.正则表达式
a.输出该文件里所有包含root的行
[root@localhost jizuo]# awk '/root/{print $1}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
dockerroot:x:985:979:Docker
输出以冒号作为分隔符的第五列中包含root的整行数据
[root@localhost jizuo]# awk -F ':' '$5~/root/{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
布尔表达式
[root@localhost jizuo]# awk -F: '$1=="root"&&$5=="root"{print $1","$5}' /etc/passwd
root,root
3.与if,while,数组的配合使用
题目1:将该服务器目前tcp连接各个状态及个数输出
先把最后一行取出来,然后利用数组和for循环对各个状态进行计数
第二种方法是利用sort和uniq进行计数
[root@localhost jizuo]# netstat -an|awk '/^tcp/{++s[$NF]}END{for(a in s)print a,s[a]}'
LISTEN 22
ESTABLISHED 13
TIME_WAIT 61
SYN_SENT 54
[root@localhost jizuo]# netstat -an|awk '/^tcp/{print $NF}'|sort -n|uniq -c
13 ESTABLISHED
22 LISTEN
54 SYN_SENT
60 TIME_WAIT
题目2:统计 web 日志访问流量,要求输出访问次数,请求页面或图片,每个请求的总大小,总访问流量的大小汇总
awk '{a[$7]+=$10;++b[$7];total+=$10}END{for(x in a)print b[x],x,a[x]|"sort -rn -k1";print
"total size is :"total}' /app/log/access_log
total size is :172230
21 /icons/poweredby.png 83076
14 / 70546
8 /icons/apache_pb.gif 18608
4.常用函数
a.替换函数gsub
[root@localhost jizuo]# awk 'BEGIN{info="this is a test2010test!";gsub(/[0-9]+/,"!",info);print info}'
this is a test!test!
b.索引查询函数index
[root@localhost jizuo]# awk 'BEGIN{info="this is a test2010test!";print index(info,"test")?"ok":"no found";}'
ok
[root@localhost jizuo]# awk 'BEGIN{info="this is a test2010test!";print index(info,"testt")?"ok":"no found";}'
no found
c.split函数
[root@localhost jizuo]# awk 'BEGIN{info="this is a test";split(info,tA," ");print length(tA);for (k in tA){print k,tA[k];}}'
4
4 test
1 this
2 is
3 a
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。