首页 > 代码库 > awk编程之数组、控制流(长期更新)
awk编程之数组、控制流(长期更新)
数组篇:
数组格式 array[index]=value
统计nginx的access.log日志中访问最多的10个IP
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
统计访问状态码为404的IP以及出现次数
[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
awk的if用法(如果不是开发部就打印,否则输出none)
[root@bogon test]# awk ‘{if($4!~/kaifabu/){print $0}else{print "none"}}‘ date
awk的for的用法,打印1到10
[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查找name是li的行,匹配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.txt和b.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];next,next是continue的意思,会继续判断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==NR,a[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
本文出自 “12384524” 博客,请务必保留此出处http://12394524.blog.51cto.com/12384524/1894098
awk编程之数组、控制流(长期更新)