以下知识点可能有不对之处,请参考最新Awk学习文章:http://lizhenliang.blog.51cto.com/7876557/1892112

知识点:

1)数组

数组是用来存储一系列值的变量,可通过索引来访问数组的值。

Awk中数组称为关联数组,因为它的下标(索引)可以是数字也可以是字符串。

下标通常称为键,数组元素的键和值存储在Awk程序内部的一个表中,该表采用散列算法,因此数组元素是随机排序。

数组格式:array[index]=value

1、Nginx日志分析

日志格式:'$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"'

日志记录:27.189.231.39 - - [09/Apr/2016:17:21:23 +0800] "GET /Public/index/images/icon_pre.png HTTP/1.1" 200 44668 "http://www.test.com/Public/index/css/global.css" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36" "-"

    1)统计日志中访问最多的10个IP

思路:对第一列进行去重,并输出出现的次数

方法1:$ awk '{a[$1]++}END{for(i in a)print a[i],i|"sort -k1 -nr|head -n10"}' access.log

方法2:$ awk '{print $1}' access.log |sort |uniq -c |sort -k1 -nr |head -n10

说明:a[$1]++ 创建数组a,以第一列作为下标,使用运算符++作为数组元素,元素初始值为0。处理一个IP时,下标是IP,元素加1,处理第二个IP时,下标是IP,元素加1,如果这个IP已经存在,则元素再加1,也就是这个IP出现了两次,元素结果是2,以此类推。因此可以实现去重,统计出现次数。

    2)统计日志中访问大于100次的IP

方法1:$ awk '{a[$1]++}END{for(i in a){if(a[i]>100)print i,a[i]}}' access.log

方法2:$ awk '{a[$1]++;if(a[$1]>100){b[$1]++}}END{for(i in b){print i,a[i]}}' access.log

说明:方法1是将结果保存a数组后,输出时判断符合要求的IP。方法2是将结果保存a数组时,并判断符合要求的IP放到b数组,最后打印b数组的IP。

  3)统计2016年4月9日一天内访问最多的10个IP

思路:先过滤出这个时间段的日志,然后去重,统计出现次数

方法1:$ awk '$4>="[9/Apr/2016:00:00:01" && $4<="[9/Apr/2016:23:59:59" {a[$1]++}END{for(i in a)print a[i],i|"sort -k1 -nr|head -n10"}' access.log

方法2:$ sed -n '/\[9\/Apr\/2016:00:00:01/,/\[9\/Apr\/2016:23:59:59/p' access.log |sort |uniq -c |sort -k1 -nr |head -n10  #前提开始时间与结束时间日志中必须存在

    4)统计当前时间前一分钟的访问数

思路:先获取当前时间前一分钟对应日志格式的时间,再匹配统计

$ date=$(date -d '-1 minute' +%d/%b/%Y:%H:%M);awk -vdate=$date '$0~date{c++}END{print c}' access.log

$ date=$(date -d '-1 minute' +%d/%b/%Y:%H:%M);awk -vdate=$date '$4>="["date":00" && $4<="["date":59"{c++}END{print c}' access.log

$ grep -c $(date -d '-1 minute' +%d/%b/%Y:%H:%M) access.log

说明:date +%d/%b/%Y:%H:%M --> 09/Apr/2016:01:55

    5)统计访问最多的前10个页面($request)

$ awk '{a[$7]++}END{for(i in a)print a[i],i|"sort -k1 -nr|head -n10"}' access.log

  6)统计每个URL访问内容的总大小($body_bytes_sent)

$ awk '{a[$7]++;size[$7]+=$10}END{for(i in a)print a[i],size[i],i}' access.log

    7)统计每个IP访问状态码数量($status)

$ awk '{a[$1" "$9]++}END{for(i in a)print i,a[i]}' access.log

  8)统计访问状态码为404的IP及出现次数

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

2、两个文件对比

文件内容如下:

$ cat a

1

2

3

4

5

6

$ cat b

3

4

5

6

7

8

    1)找出相同记录

方法1:$ awk 'FNR==NR{a[$0];next}($0 in a)' a b

3

4

5

6

解释前,先看下FNR和NR区别:

$ awk '{print NR,$0}' a b

1 1

2 2

3 3

4 4

5 5

6 6

7 3

8 4

9 5

10 6

11 7

12 8

$ awk '{print FNR,$0}' a b

1 1

2 2

3 3

4 4

5 5

6 6

1 3

2 4

3 5

4 6

5 7

6 8

可以看出NR是处理一行记录,编号就会加1,同时也可以看到awk将两个文件当成一个合并后的文件处理。

而FNR则是处理一行记录,编号也会加1,但是,处理到第二个文件时,编号重新计数。

说明:FNR和NR是内置变量。FNR==NR常用于对两个文件处理,这个例子可以理解为awk将两个文件当成一个文件处理。

处理a文件时,FNR是等于NR的,条件为真,执行a[$0],next表达式,意思是将每条记录存放到a数组作为下标(无元素),next是跳出,类似于continue,不执行后面表达式。

执行过程以此类推,直到处理b件时,FNR不等于NR(FNR重新计数是1,NR继续加1是7),条件为假,不执行后面a[$0],next表达式,直接执行($0 in a)表达式,这句意思是处理b文件第一条继续判断是否在a数组中,如果在则打印这条记录,以此类推。

这样可能更好理解些:

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

方法2:

$ awk 'FNR==NR{a[$0]=1;next}(a[$0])' a b   #小括号可以不加

$ awk 'FNR==NR{a[$0]=1;next}(a[$0]==1)' a b

$ awk 'FNR==NR{a[$0]=1;next}{if(a[$0]==1)print}' a b

$ awk 'FNR==NR{a[$0]=1}FNR!=NR&&a[$0]==1' a b

说明:先要知道后面的a[$0]不是一个数组,而是通过下标(b文件每条记录)来访问a数组元素。如果a[b的一行记录]获取的a数组元素是1,则为真,也就是等于1,打印这条记录,否则获取不到元素,则为假。

方法3:

$ awk 'ARGIND==1{a[$0]=1}ARGIND==2&&a[$0]==1' a b

$ awk 'FILENAME=="a"{a[$0]=1}FILENAME=="b"&&a[$0]==1' a b

说明:ARGIND内置变量,处理文件标识符,第一个文件为1,第二个文件为2。FILENAME也是内置变量,表示输入文件的名字

方法4:$ sort a b |uniq -d

方法5:$ grep -f a b

    2)找不同记录(同上,取反)

$ awk 'FNR==NR{a[$0];next}!($0 in a)' a b

$ awk 'FNR==NR{a[$0]=1;next}!a[$0]' a b

$ awk 'ARGIND==1{a[$0]=1}ARGIND==2&&a[$0]!=1' a b

$ awk 'FILENAME=="a"{a[$0]=1}FILENAME=="b"&&a[$0]!=1' a b

7

8

方法2:$ sort a b |uniq -d

方法3:$ grep -vf a b

3、合并两个文件

1)将d文件性别合并到c文件

$ cat c

zhangsan 100

lisi 200

wangwu 300

$ cat d

zhangsan man

lisi woman

方法1:$ awk  'FNR==NR{a[$1]=$0;next}{print a[$1],$2}' c d

zhangsan 100  man

lisi 200 woman

wangwu 300 man

方法2:$ awk  'FNR==NR{a[$1]=$0}NR>FNR{print a[$1],$2}' c d

说明:NR==FNR匹配第一个文件,NR>FNR匹配第二个文件,将$1为数组下标

方法3:$ awk 'ARGIND==1{a[$1]=$0}ARGIND==2{print a[$1],$2}' c d

2)将a.txt文件中服务名称合并到一个IP中

$ cat a.txt

192.168.2.100 : httpd

192.168.2.100 : tomcat

192.168.2.101 : httpd

192.168.2.101 : postfix

192.168.2.102 : mysqld

192.168.2.102 : httpd

$ awk -F: -vOFS=":" '{a[$1]=a[$1] $2}END{for(i in a)print i,a[i]}' a.txt

$ awk -F: -vOFS=":" '{a[$1]=$2 a[$1]}END{for(i in a)print i,a[i]}' a.txt

192.168.2.100 : httpd  tomcat

192.168.2.101 : httpd  postfix

192.168.2.102 : mysqld  httpd

说明:a[$1]=$2 第一列为下标,第二个列是元素,后面跟的a[$1]是通过第一列取a数组元素(服务名),结果是$1=$2 $2,并作为a数组元素。

3)将第一行附加给下面每行开头

$ cat a.txt

xiaoli

a 100

b 110

c 120

$ awk 'NF==1{a=$0;next}{print a,$0}' a.txt

$ awk 'NF==1{a=$0}NF!=1{print a,$0}' a.txt

xiaoli  a 100

xiaoli  b 110

xiaoli  c 120

4、倒叙列打印文本

$ cat a.txt

xiaoli   a 100

xiaoli   b 110

xiaoli   c 120

$ awk '{for(i=NF;i>=1;i--){printf "%s ",$i}print s}' a.txt

100 a xiaoli

110 b xiaoli

120 c xiaoli

$ awk '{for(i=NF;i>=1;i--)if(i==1)printf $i"\n";else printf $i" "}' a.txt

说明:利用NF降序输出,把最后一个域作为第一个输出,然后自减,print s或print ""打印一个换行符

5、从第二列打印到最后

方法1:$ awk '{for(i=2;i<=NF;i++)if(i==NF)printf $i"\n";else printf $i" "}' a.txt

方法2:$ awk '{$1=""}{print $0}' a.txt

a 100

b 110

c 120

6、将c文件中第一列放到到d文件中的第三列

$ cat c

a

b

c

$ cat d

1 one

2 two

3 three

方法1:$ awk 'FNR==NR{a[NR]=$0;next}{$3=a[FNR]}1' c d

说明:以NR编号为下标,元素是每行,当处理d文件时第三列等于获取a数据FNR(重新计数1-3)编号作为下标。

方法2:$ awk '{getline f<"c";print $0,f}' d

1 one a

2 two b

3 three c

1)替换第二列

$ awk '{getline f<"c";gsub($2,f,$2)}1' d

1 a

2 b

3 c

2)替换第二列的two

$ awk '{getline f<"c";gsub("two",f,$2)}1' d

1 one

2 b

3 three

7、数字求和

方法1:$ seq 1 100 |awk '{sum+=$0}END{print sum}'

方法2:$ awk 'BEGIN{sum=0;i=1;while(i<=100){sum+=i;i++}print sum}'

方法3:$ awk 'BEGIN{for(i=1;i<=100;i++)sum+=i}END{print sum}' /dev/null

方法4:$ seq -s + 1 100 |bc

8、每隔三行添加一个换行符或内容

方法1:$ awk '$0;NR%3==0{printf "\n"}' a

方法2:$ awk '{print NR%3?$0:$0"\n"}' a

方法3:$ sed '4~3s/^/\n/' a

9、字符串拆分

方法1:

$ echo "hello" |awk -F '' '{for(i=1;i<=NF;i++)print $i}'

$ echo "hello" |awk -F '' '{i=1;while(i<=NF){print $i;i++}}'

h

e

l

l

o

方法2:

$ echo "hello" |awk '{split($0,a,"''");for(i in a)print a[i]}'  #无序

l

o

h

e

l

10、统计字符串中每个字母出现的次数

$ echo a,b.c.a,b.a |tr "[,. ]" "\n" |awk -F '' '{for(i=1;i<=NF;i++)a[$i]++}END{for(i in a)print i,a[i]|"sort -k2 -rn"}'

a 3

b 2

c 1

11、第一列排序

$ awk '{a[NR]=$1}END{s=asort(a,b);for(i=1;i<=s;i++){print i,b[i]}}' a.txt

说明:以每行编号作为下标值为$1,并将a数组值放到数组b,a下标丢弃,并将asort默认返回值(原a数组长度)赋值给s,使用for循环小于s的行号,从1开始到数组长度打印排序好的数组。

12、删除重复行,顺序不变

$ awk '!a[$0]++' file

博客地址:http://lizhenliang.blog.51cto.com

QQ群:323779636(Shell/Python运维开发群)

13、删除指定行

删除第一行:

$ awk 'NR==1{next}{print $0}' file #$0可省略

$ awk 'NR!=1{print}' file

$ sed '1d' file

$ sed -n '1!p' file

14、在指定行前后加一行

在第二行前一行加txt:

$ awk 'NR==2{sub('/.*/',"txt\n&")}{print}' a.txt

$ sed'2s/.*/txt\n&/' a.txt

在第二行后一行加txt:

$ awk 'NR==2{sub('/.*/',"&\ntxt")}{print}' a.txt

$ sed'2s/.*/&\ntxt/' a.txt

15、通过IP获取网卡名

$ ifconfig |awk -F'[: ]' '/^eth/{nic=$1}/192.168.18.15/{print nic}'

16、浮点数运算(数字46保留小数点)

$ awk 'BEGIN{print 46/100}'

$ awk 'BEGIN{printf "%.2f\n",46/100}'

$ echo 46|awk '{print $0/100}'

$ echo 'scale=2;46/100' |bc|sed 's/^/0/'

$ printf "%.2f\n" $(echo "scale=2;46/100" |bc)

结果:0.46

17、替换换行符为逗号

$ cat a.txt

1

2

3

替换后:1,2,3

方法1:

$ awk '{s=(s?s","$0:$0)}END{print s}' a.txt

说明:三目运算符(a?b:c),第一个s是变量,s?s","$0:$0,第一次处理1时,s变量没有赋值初值是0,0为假,结果打印1,第二次处理2时,s值是1,为真,结果1,2。以此类推,小括号可以不写。

方法2:

$ tr '\n' ',' < a.txt

方法3:

$ sed ':a;N;s/\n/,/;$!b a' a.txt

说明:第一个标签a,先读取第一行记录1追加到模式空间,此时模式空间内容是1$,执行$!b($!最后一行不跳转,b是控制流跳转命令)跳转到a标签,继续读取第二行记录2追加到模式空间,因为使用N命令,每个记录以换行符(\n)分割,此时模式空间内容是1\n2$,执行将换行符替换逗号命令,继续跳转到a标签...

方法4:

$ sed ':a;$!N;s/\n/,/;t a' a.txt

说明:与上面类似,其中t是测试命令,当上一个命令(替换)执行成功才跳转。

方法5:

$ awk '{if($0!=3)printf "%s,",$0;else print $0}' a.txt

说明:3是文本最后一个数

方法6:

while read line; do

a+=($line)

done < a.txt

echo ${a[*]} |sed 's/ /,/g'

说明:将每行放到数组,然后替换

18、把奇数换行符去掉

$ cat b.txt

string

number

a

1

b

2

$ awk 'ORS=NR%2?"\t":"\n"' b.txt  #把奇数行换行符去掉

$ xargs -n2 < a.txt  #将两个字段作为一行

string number

a 1

b 2

19、费用统计

$ cat a.txt

姓名             费用   数量

zhangsan        8000    1

zhangsan        5000    1

lisi            1000    1

lisi            2000    1

wangwu          1500    1

zhaoliu         6000    1

zhaoliu         2000    1

zhaoliu         3000    1

统计每人总费用、总数量:

$ awk '{name[$1]++;number[$1]+=$3;money[$1]+=$2}END{for(i in name)print i,number[i],money[i]}' a.txt

zhaoliu 3 11000

zhangsan 2 13000

wangwu 1 1500

lisi 2 3000

20、打印乘法口诀

方法1:

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

1x1=1

1x2=2 2x2=4

1x3=3 2x3=6 3x3=9

1x4=4 2x4=8 3x4=12 4x4=16

1x5=5 2x5=10 3x5=15 4x5=20 5x5=25

1x6=6 2x6=12 3x6=18 4x6=24 5x6=30 6x6=36

1x7=7 2x7=14 3x7=21 4x7=28 5x7=35 6x7=42 7x7=49

1x8=8 2x8=16 3x8=24 4x8=32 5x8=40 6x8=48 7x8=56 8x8=64

1x9=9 2x9=18 3x9=27 4x9=36 5x9=45 6x9=54 7x9=63 8x9=72 9x9=81

方法2:

#!/bin/bash

for ((i=1;i<=9;i++)); do

for ((j=1;j<=i;j++)); do

result=$(($i*$j))

#let "result=i*j"

echo -n "$i*$j=$result "

done

echo

done

21、只打印奇数或偶数行

打印奇数行:

方法1:

$ seq 1 5 |awk 'i=!i'

说明:先知道对于数值运算,未定义变量初值为0,对于字符运算,未定义变量初值为空字符串。

读取第一行记录,然后进行模式匹配,i是未定义变量,也就是i=!0,!取反意思。感叹号右边是个布尔值,0或空字符串为假,非0或非空字符串为真,!0就是真,因此i=1,条件为真打印第一条记录。

没有print为什么会打印呢?因为模式后面没有动作,默认会打印整条记录。

读取第二行记录,进行模式匹配,因为上次i的值由0变成了1,此时就是i=!1,条件为假不打印。

读取第三行记录,因为上次条件为假,i恢复初值为0,继续打印。以此类推...

可以看出,运算时并没有判断记录,而是利用布尔值真假判断。

方法2:

$ seq 1 5 |awk 'NR%2!=0'

方法3:

$ seq 1 5 |sed -n '1~2p'

说明:步长,每隔一行打印一次

方法4:

$ seq 1 5 |sed -n 'p;n'

说明:先打印第一行,执行n命令读取当前行的下一行2,放到模式空间,后面再没有打印模式空间行操作,所以只保存不打印,同等方式继续打印第三行。

1

3

5

    打印偶数行:

$ seq 1 5 |awk '!(i=!i)'

$ seq 1 5 |awk 'NR%2==0'

$ seq 1 5 |sed -n '0~2p'

$ seq 1 5 |sed -n 'n;p'

说明:读取当前行的下一行2,放到模式空间,使用p命令打印模式空间的行,输出2。

Awk使用案例总结(运维必会)相关推荐

  1. mysql 建表语句 及完整案例_Linux运维必会的100道MySql面试题之(一)

    01 如何启动MySql服务 /etc/init.d/mysqld start service mysqld start Centos 7.x 系统 sysctl start mysqld02 检测端 ...

  2. 新开班全栈Linux运维-Linux云计算运维与高级架构班课程 全新自动化运维必学课程

    新开班全栈Linux运维-Linux云计算运维与高级架构班课程 全新自动化运维必学课程 全栈Linux运维的课程意义,在于让同学们从Liunx基础课程开始,一路直通Liunx运维高级架构师的级别.全新 ...

  3. 全栈Linux运维-Linux云计算运维与高级架构班课程 全新自动化运维必学课程

    全栈Linux运维-Linux云计算运维与高级架构班课程 全新自动化运维必学课程 全栈Linux运维的课程意义,在于让同学们从Liunx基础课程开始,一路直通Liunx运维高级架构师的级别.全新的Li ...

  4. 运维之道 | Linux运维必会的MySQL企业面试题

    Linux运维必会的MySQL企业面试题 基础笔试命令 1.开启MySQL服务 [root@localhost ~]# /etc/init.d/mysqld start [root@localhost ...

  5. 经典案例复盘——运维专家讲述如何实现K8S落地

    经典案例复盘--运维专家讲述如何实现K8S落地 背景介绍 运满满自开始微服务改造以来,线上线下已有数千个微服务的 Java 实例在运行中.这些 Java 实例部署在数百台云服务器或虚机上,除少数访问量 ...

  6. (转)Awk使用案例总结(运维必会)

    以下知识点可能有不对之处,请参考最新Awk学习文章:http://lizhenliang.blog.51cto.com/7876557/1892112 原文:http://blog.51cto.com ...

  7. Linux运维必会的实战编程笔试题(19题)

    以下Linux运维笔试面试编程题,汇总整理自老男孩.马哥等培训机构,由运维派根据实战需求,略有调整: 企业面试题1:(生产实战案例):监控MySQL主从同步是否异常,如果异常,则发送短信或者邮件给管理 ...

  8. 运维必知的23个经验教训,值得收藏!

    今天小编给大家分享一下运维人员必知的23个经验教训,值得读一读! 一.线上操作规范 1. 测试使用 当初学习Linux的使用,从基础到服务到集群,都是在虚拟机做的,虽然老师告诉我们跟真机没有什么差别, ...

  9. Jenkins持续集成案例之-运维部署方式

    大家在运维过程中,网站部署是运维的工作之一,中小型公司传统网站部署的流程大致分为如下方法: 需求分析-原型设计-开发代码-提交测试-内网部署-确认上线-备份数据-外网更新-最终测试,如果发现外网部署的 ...

最新文章

  1. python爬虫入门代码-Python爬虫入门(一) 网络爬虫之规则
  2. linux opendir readdir closedir 的使用
  3. Android工程模块化平台的设计
  4. 汽车拼图游戏 - 汽车积木拼图游戏
  5. 计算机文化基础知识点文件,计算机文化基础知识点.doc
  6. ubuntu开启SSH服务和允许root远程SSH登录
  7. Android之用Handler实现主线程和子线程互相通信以及子线程和子线程之间的通信
  8. python解析器原理_Python程序运行原理图文解析
  9. webstorm 添加php插件,webstorm常用插件分享
  10. 绮莉:一个超爱团队,为团队疯狂打call的少女
  11. 八、高级依赖关系配置
  12. Intent常用使用汇总
  13. 解除 网课失去焦点/离开页面 就自动暂停 的限制
  14. monkey入门研究
  15. 青岛飞阳计算机学校,青岛通济实验学校:综艺比赛 青春飞扬
  16. 喜迎B+轮融资,ThingJS母公司优锘科技成为新基建的一匹黑马
  17. 上古卷轴5捏脸php导入,上古卷轴5捏脸预设导入 上古卷轴5捏脸预设怎么导入
  18. aix oracle 10.2.0.1 升级 10.2.0.4,【江枫 】AIX平台升级到Oracle10.2.0.4的几个问题
  19. 基于QT的游戏修改器
  20. 架构师的5大基本能力

热门文章

  1. PK朱广权的手语数字人,现在要到医院银行上岗了
  2. 特斯拉纯视觉FSD版本Bug频发!马斯克:不认真测试的车主就取消资格
  3. 零下273.14度稳定运行!中科院自主研发稀释制冷机,高端科研仪器取得突破进展...
  4. 涂鸦智能冲刺IPO,不卖硬件的AIoT公司,团队阿里云出身,腾讯是大股东
  5. 这老哥把GPU当暖气用,省钱了
  6. 让Hinton后悔投少了的AI公司:吴恩达弟子徒孙创办,LeCun李飞飞Jeff Dean投资,产品让人无法拒绝...
  7. linux 无敌kill -KILL processID
  8. java之 ------ 可变參数和卫条件
  9. bzoj1874: [BeiJing2009 WinterCamp]取石子游戏
  10. ES6新特性:Javascript中的Reflect对象