数组篇:
数组格式 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数组方法实现:
[[email protected] test]# awk ‘{++a[$1]} END{for(i in a)print a[i] "\t" i|"sort -nr|head -10"}‘ access.log
其他方法实现:
[[email protected] test]# awk ‘{print $1}‘ access.log |sort|uniq -c|sort -nr|head -10
统计访问状态码为404的IP以及出现次数
[[email protected] 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)
[[email protected] test]# awk ‘{if($4!~/kaifabu/){print $0}else{print "none"}}‘ date
awk的for的用法,打印1到10
[[email protected] 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}}‘
删除指定行:
方法一:[[email protected] test]# awk ‘NR==1{next}{print}‘ date
方法二:[[email protected] test]# awk ‘NR!=1{print}‘ date
用awk查找name是li的行,匹配1次就停止。
[[email protected] test]# awk ‘$1~/li/&&!a++{print}‘ data
删除第一列重复的行(只打印第一个匹配到的)
[[email protected] 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也会打印。
匹配第四列重复出现的次数
[[email protected] test]# awk ‘{a[$4]++}END{for(i in a)print a[i] "\t" i}‘ data
除了第三列不打印
[[email protected] test]# awk ‘{$1="";print}‘ data
打印倒数第二列
[[email protected] test]# awk ‘{print $(NF-1)}‘ data
第二列匹配数字的行,如果取反,则$2!~/[0-9]/
[[email protected] test]# awk ‘$2~/[0-9]/ {print $0}‘ data
第一列匹配到某个字符串
[[email protected] test]# awk ‘$1~/an/ {print $0}‘ data
统计全文单词出现次数,本题是针对 li 如果是 liu 不算
[[email protected] test]# awk ‘{for(i=1;i<=NF;i++)if($i=="li")++sum}END{print sum}‘ data
如果要让liu也算,则
[[email protected] test]# awk -F‘li‘ ‘{a+=NF-1}END{print a}‘ data
随机生成6位数
[[email protected] test]# echo | awk ‘BEGIN{srand();print rand()*1000000}‘
求第三列的最大值
[[email protected] test]# awk ‘BEGIN{mxa=0}{if($3+0>max+0)max=$3}END{print "MAX=",max}‘ data
求第三列的最小值(如果是针对上面的文本,需要先过滤出数字)
[[email protected] test]# awk ‘BEGIN {min = 65536} {if ($3+0 < min+0) min=$3} END {print "Min=", min}‘ data
第三列的求和
[[email protected] test]# awk ‘{sum+=$3}END{print sum}‘ data
第三列求平均值(前提也是需要先过滤出第三列带数字的)
[[email protected] test]# awk ‘{sum+=$3}END{print sum/NR}‘ data
文件合并处理
找出a.txt和b.txt两个文件相同的行
[[email protected] test]# cat a.txt
a
b
c
[[email protected] test]# cat b.txt
1
a
2
3
[[email protected] 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
其他方法:[[email protected] test]# grep -f a.txt b.txt
找不同的行:
[[email protected] test]# awk ‘FNR==NR{a[$0];next}!($0 in a)‘ a.txt b.txt
合并文件,将b.txt的第二列增加到a.txt中去,名字相互对应(此题有BUG,待更新)
[[email protected] test]# cat a.txt
zhang100
li200
wang 300
[[email protected] test]# cat b.txt
zhang man
liwomen
[[email protected] 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合并文件,然后再进行打印兴许会更好:
[[email protected] test]# paste a.txt b.txt |awk ‘{if($1==$3)print $1"\t"$2"\t"$4}‘
zhang 100 man
li 200 women