数组篇:

数组格式    array[index]=value

 

 

统计nginxaccess.log日志中访问最多的10IP

101.121.182.144 - - [24/Jan/2017:11:25:59 +0800] "POST /home/activity/new-cow-interface!returnNewCowMsg.action HTTP/1.1" 200 2 -uin=50863819- "-" "Java/1.6.0_33" "-""-" "0.067"

awk数组方法实现:

[root@bogon test]# awk '{++a[$1]} END{for(i in a)print a[i] "\t" i|"sort -nr|head -10"}' access.log

其他方法实现:

[root@bogon test]# awk '{print $1}' access.log |sort|uniq -c|sort -nr|head -10

 

统计访问状态码为404IP以及出现次数

[root@bogon test]# awk '{if($9~/404/)a[$1" "$9]++}END{for(i in a)print i,a[i]}' access.log

 

 

 

 

 

data

name    id  salary  department  

liu     11  8000    yunweibu

zhang   01  8800    renshibu

li      03  7000    kefubu

wang    02  12000   kaifabu

yu      88  7900    yunweibu

song    19  20000   kaifabu

xue     07  6500    shichangbu

dong    11  11000   kaifabu

li      13  9900    chichangbu

 

 

awkif用法(如果不是开发部就打印,否则输出none

[root@bogon test]# awk '{if($4!~/kaifabu/){print $0}else{print "none"}}' date

 

awkfor的用法,打印110

[root@bogon test]# echo |awk '{for(i=1;i<=10;i++){print i}}'

 

for打印乘法口诀:

echo |awk '{for(n=0;n++<9;){for(i=0;i++<n;)printf i"x"n"="i*n" ";print}}'

 

删除指定行:

方法一:[root@bogon test]# awk 'NR==1{next}{print}' date

方法二:[root@bogon test]# awk 'NR!=1{print}' date

 

awk查找nameli的行,匹配1次就停止。

[root@bogon test]# awk '$1~/li/&&!a++{print}' data

 

删除第一列重复的行(只打印第一个匹配到的)

[root@bogon test]# awk '!a[$1]++' data

 

打印奇数行

方法一:awk 'i=!i'

方法二:awk '{if(NR%2==1){print}}'      (依次类推可以打印任意步长)

其他方法:sed -n '1~2 p'      (第一行开始,步长是2)

打印偶数行

awk '!(i=!i)'

解释:i没有被定义,默认值为空字符串或者是0,打印奇数行开始时候i=!0,0是假,!0是真,i=1条件为真,所有会打印,该模式判断为真默认会打印整行记录,所以不加print也会打印。

 

 

匹配第四列重复出现的次数

[root@bogon test]# awk '{a[$4]++}END{for(i in a)print a[i] "\t" i}' data

 

除了第三列不打印

[root@bogon test]# awk '{$1="";print}' data

 

打印倒数第二列

[root@bogon test]# awk '{print $(NF-1)}' data

 

第二列匹配数字的行,如果取反,则$2!~/[0-9]/

[root@bogon test]# awk '$2~/[0-9]/ {print $0}' data

 

第一列匹配到某个字符串

[root@bogon test]# awk '$1~/an/ {print $0}' data

 

统计全文单词出现次数,本题是针对 li  如果是 liu 不算

[root@bogon test]# awk '{for(i=1;i<=NF;i++)if($i=="li")++sum}END{print sum}' data

 

如果要让liu也算,则

[root@bogon test]# awk -F'li' '{a+=NF-1}END{print a}' data   

 

随机生成6位数

[root@bogon test]# echo | awk 'BEGIN{srand();print rand()*1000000}'

 

求第三列的最大值

[root@bogon test]# awk 'BEGIN{mxa=0}{if($3+0>max+0)max=$3}END{print "MAX=",max}' data

 

求第三列的最小值(如果是针对上面的文本,需要先过滤出数字)

[root@bogon test]# awk 'BEGIN {min = 65536} {if ($3+0 < min+0) min=$3} END {print "Min=", min}' data

 

第三列的求和

[root@bogon test]# awk '{sum+=$3}END{print sum}' data

 

第三列求平均值(前提也是需要先过滤出第三列带数字的)

[root@bogon test]# awk '{sum+=$3}END{print sum/NR}' data

 

 

 

 

文件合并处理

 

找出a.txtb.txt两个文件相同的行

[root@bogon test]# cat a.txt

a

b

c

[root@bogon test]# cat b.txt

1

a

2

3

 

[root@bogon test]# awk 'FNR==NR{a[$0];next}($0 in a)' a.txt b.txt

a

解释:合并文件后,NR会依次记录行数,而FNR会在第二个文件进入后重新编对行号,处理文件a.txt时候FNR==NR,条件为真,会执行a[$0];nextnextcontinue的意思,会继续判断FNR==NR,直到处理文件b.txt时,FNR==NR条件为假执行($0 in a),这句话的意思是,处理文件b.txt时候,如果该行在a里面,则打印,否则不打印。或者这样更好理解:

awk 'NR==FNR{a[$0]}NR>FNR{if($0 in a)print $0}'  a.txt b.txt

 

其他方法:[root@bogon test]# grep -f a.txt b.txt

 

 

找不同的行:

[root@bogon test]# awk 'FNR==NR{a[$0];next}!($0 in a)' a.txt b.txt

 

 

合并文件,将b.txt的第二列增加到a.txt中去,名字相互对应(此题有BUG,待更新)

[root@bogon test]# cat a.txt

zhang100

li200

wang 300

[root@bogon test]# cat b.txt

zhang man

liwomen

[root@bogon test]# awk 'FNR==NR{a[$1]=$0;next}{print a[$1],$2}'  a.txt b.txt

zhang100 man

li200 women

解释:如果FNR==NRa[zhang]=a.txt文件中的行,否则打印。


用paste合并文件,然后再进行打印兴许会更好:

[root@bogon test]# paste a.txt b.txt |awk '{if($1==$3)print $1"\t"$2"\t"$4}'

zhang 100 man

li 200 women