awk生产环境实战案例:


(一):请执行命令取出linux中eth0的IP地址

法1: ifconfig eth0| grep 'inet addr'| awk -F":" '{print $2}'|awk '{print $1}'

法2: ifconfig eth0| grep 'inet addr'| cut -d: -f2|cut -d" " -f1

法3: ifconfig eth0| grep 'inet addr'| cut -d: -f2| awk '{print $1}'

法4: ifconfig eth0| awk -F '[ :]+' 'NR==2 {print $4}'

#法4为最佳实践

我们来说明下这个简单易用的好办法:

提示:本题NR是行号,分隔符+号匹配,[]里一个或多个任意一个分隔符,这里就是匹配一个或多个冒号或空格。

1awk -F 后面跟分隔符,其中[空格:]多分隔符写法,意思是以空格或冒号做分隔,后面的"+"号是正则表达式,意思是匹配前面空格或冒号,两者之一的1个或1个以上。

2NR==2sed -n "2p",相当,意思都是选择第几行,例:

[root@oldboy ~]# ifconfig eth0|awk NR==2
 inet addr:10.0.0.185  Bcast:10.0.0.255  Mask:255.255.255.0


3)指定awk -F '[ :]+'分隔符后,不同字符串被分隔的列依次为:


inet

addr

10.0.0.185

  Bcast:10.0.0.255  Mask:255.255.255.0

第一列

第二列

第三列

第四列

  后面忽略不计。

4)整个答案awk部分意思是,通过NR==2取出第二行,然后,通过-F '[ :]+多分隔符正则匹配,然后通过{print $4}打印出第四列 

5)掌握了理论要去实践验证才是科学严谨的学习态度,好,来几个例子实践说话吧。

[root@oldboy ~]# echo ---1:----2|awk -F '[-:]+' '{print $2}'     
1
[root@oldboy ~]# echo ---1:----2|awk -F '[-:]+' '{print $3}'     
2
[root@oldboy ~]# echo ---1:::::2|awk -F '[-:]+' '{print $3}'    
2




(二):生产服务器netstat tcp连接状态

法1: netstat -ant|awk '{S[$NF]++}END{for(k in S) print k,S[k]}'

法2: netstat -ant|awk '{S[$6]++}END{for(k in S) print k,S[k]}'

法3: netstat -ant |awk '/^tcp/ {S[$NF]++} END {for(a in S) print a,S[a]}'

法4: netstat -ant |awk '/^tcp/ {S[$6]++} END {for(a in S) print a,S[a]}'

awk庖丁解牛

netstat -n |awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

命令拆分

功能说明

/^tcp/

过滤出以tcp开头的行,“^”为正则表达式用法,以...开头,这里是过滤出以tcp开头的行。

S[]

定义了一个名叫S的数组,在awk中,数组下标通常从 1 开始,而不是 0。

NF

当前记录里域个数,默认以空格分隔,如上所示的记录,NF域个数等于6

$NF

表示一行的最后一个域的值,如上所示的记录,$NF也就是$6,表示第6个字段的值,也就是SYN_RECVTIME_WAIT等。

S[$NF]

表示数组元素的值,如上所示的记录,就是S[TIME_WAIT]状态的连接数

++S[$NF]

表示把某个数加一,如上所示的记录,就是把S[TIME_WAIT]状态的连接数加一

END


for(key in S)

遍历S[]数组

print key,”\t”,S[key]

打印数组的键和值,中间用\t制表符分割,显示好一些。

小例子测试:

[root@ywxi test]# cat test.txt 
001 name wodi 12k
002 name yingsui 15k
003 name jeacen 10k
004 name kuqi 8k
005 name yideng 10k
006 name xiaofan 8k
[root@ywxi test]# awk '{S[$NF]++} END {for(a in S) print a,S[a]}' test.txt     
15k 1
 8k 2
10k 2
12k 1
[root@ywxi test]# awk '{S[$4]++} END {for(a in S) print a,S[a]}' test.txt  
15k 1
 8k 2
10k 2
12k 1
[root@ywxi test]# awk '{print $4}' test.txt |sort |uniq -c |sort -nr
 2 8k
 2 10k
 1 15k
 1 12k




(三):awk数组命令生产实战拓展

假设apache日志内容access.log内容为:

[root@ywxi test]# cat access.log 
10.0.0.41 - - [03/Dec/2010:23:27:01 +0800] "HEAD /checkstatus.jsp HTTP/1.0" 200 -
10.0.0.42 - - [03/Dec/2010:23:27:01 +0800] "HEAD /checkstatus.jsp HTTP/1.0" 200 -
10.0.0.42 - - [03/Dec/2010:23:27:01 +0800] "HEAD /checkstatus.jsp HTTP/1.0" 200 -
10.0.0.47 - - [03/Dec/2010:23:27:02 +0800] "HEAD /checkstatus.jsp HTTP/1.0" 200 -
10.0.0.42 - - [03/Dec/2010:23:27:02 +0800] "HEAD /checkstatus.jsp HTTP/1.0" 200 -
10.0.0.47 - - [03/Dec/2010:23:27:02 +0800] "HEAD /checkstatus.jsp HTTP/1.0" 200 -


3.1 统计apache日志单ip访问请求数排名

法1:

[root@ywxi test]# awk '{S[$1]++} END {for(a in S) print S[a],a}' access.log |sort -rn -k2

3 10.0.0.42

2 10.0.0.47

1 10.0.0.41

#提示 $1为第一个域的内容。-k2 为对第二个字段排序,即对数量排序。

法2:

[root@ywxi test]# awk '{print $1}' access.log |sort |uniq -c |sort -rn

法3:

[root@ywxi test]# sed 's/- -.*$//g' access.log |sort |uniq -c |sort -rn

 

3.2 统计服务器当前单IP连接数最大的IP地址前十

法1: netstat -an |grep EST |awk -F '[ :]+' '{++S[$6]} END {for (key in S) print "ip:"key"----->",S[key]}' |sort -rn -k2 |head

法2: netstat -an |grep EST |awk '{print $5}' |cut -d : -f 1 |grep -v "^$" |awk '{++ETT[$1]} END {for (oldboy in ETT) print "ip:"oldboy "-----",ETT[oldboy] ''}' |sort -rn -k2 |head




(四):处理以下文件内容,将域名取出并根据域名进行计数排序处理:(百度和sohu面试题)

[root@ywxi test]# cat oldboy.log 
http://www.etiantian.org/index.html
http://www.etiantian.org/1.html
http://post.etiantian.org/index.html
http://mp3.etiantian.org/index.html
http://www.etiantian.org/3.html
http://post.etiantian.org/2.html

处理结果为:

1 mp3.etiantian.org

2 post.etiantian.org

3 www.etiantian.org

法1: cut -d "/" -f3 test.log |sort |uniq -c    

法2: awk -F "/" '{print $3}' test.log |sort |uniq -c

法3: sed 's#^http://##g' test.log|sed 's#/.*##g'|sort |uniq -c

法4: cat test.log |tr "\/" "\n"|grep etiantian|sort|uniq -c

法5: sed -e 's#^.*//\(.*etiantian.*\)/.*html#\1#g' test.log|sort|uniq -c|sort

法6: cut -d "/" -f 3 test.log |awk '{S[$1]++} END {for(a in S) print S[a],a}'

法7: awk -F "/" '{++S[$3]} END {for(key in S) print S[key],key}' test.log

法8: awk -F '[:/]+' '{print $2}' test.log |sort |uniq -c