整理的几个好一点的awk案例

一,有这么两个文本,要求以文本a的第一个字段为比较,如果文本b的第一个字段与a不符合,那么打印出该行。

$ cat a
1 a
2 f
3 5
4 8
$ cat b
1 a
2 f
3 5
5 8

这里用到FNR(记录当前处理文件的行数)  NR(记录当前处理的总行数) next(处理下一条记录,不行后边的action) awk默认执行的action print $0

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

首先NR==FNR对文本a进行处理,把$1的值作为下标放入数组a,next不会执行后面的语句,一直读到文本b不满足NR==FNR条件,这时判断文
本b的$1是否存在于数组a中的下标中,显然文本b的第一行的$1是存在于数组a的下标中的,那么条件为真,再!,注意非真即为假,为假那么不会执行该
pattern后面默认的{print]这个action动作,那么则不会输出该行,一直到第4行的$1并未存在于数组a的下标中,那么条件为假,非假为
真,则执行默认的打印,输出了该行。或许下面的写法更符合规范和便于理解:

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

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}{if($1 in a) print a[$1],$2}‘ c d

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

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

案例二,

需求:

对nginx的access.log日志分析,要求最近100次请求中状态值不是200的百分比。

日志格式如下:

192.168.123.6
- - [26/May/2015:23:44:21+0800] "GET /get_seller_info&format=json
HTTP/1.1" 200 34679"-" "Dalvik/1.6.0 (Linux; U; Android 4.4.4; MX4
ProBuild/KTU84P)" "-" "3.562"

awk  ‘{if($8 ~ /^[0-9]/)print $8}‘ filename.log | tail -100 | awk ‘{if($1!=200) s++;}END{print s*100/NR"%"}‘

解释:首先按默认分组取状态值,然后取最近100次,然后进行打印,都是基础知识点。

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

参考:http://www.tuicool.com/articles/JFnaIrY

重复的数据总是让人各种不爽,占用空间、看起来费劲等等,今天就介绍一个通过awk去除文件中重复数据的办法,awk默认是一行行来处理数据的,那我们就重点说说如何通过awk去除文件中的重复行。

  首先准备一个文本文件,随便写个文件,包含重复行数据的即可,或者你可以参考我这里的文件:

[email protected]:~/awk$ cat dup
hello world
awk
coding ants
hello world
awk
hello world
awk
coding ants
coding ants

  共有9行,后面6行都是重复的前面的几行,最终的效果应该是只显示上面重点显示的那几行,先来看看效果:

[email protected]:~/awk$ awk ‘!a[$0]++‘ dup
hello world
awk
coding ants

  在《awk程序指令模型》中介绍了awk的程序指令由模式和操作组成,即Pattern { Action }的形式,如果省略Action,则默认执行 print $0 的操作。

  实现去除重复功能的就是这里的Pattern:

!a[$0]++

  在awk中,对于未初始化的数组变量,在进行数值运算的时候,会赋予初值0,因此a[$0]=0,++运算符的特性是先取值,后加1,因此Pattern等价于

!0

  而0为假,!为取反,因此整个Pattern最后的结果为1,相当于if(1),Pattern匹配成功,输出当前记录,对于dup文件,前3条记录的处理方式都是如此。

  当读取第4行数据“hello world”的时候,a[$0]=1,取反后的结果为0,即Pattern为0,Pattern匹配失败,因此不输出这条记录,后续的数据以此类推,最终成功实现去除文件中的重复行。

时间: 2024-08-03 19:40:06

整理的几个好一点的awk案例的相关文章

awk案例学习

awk是一个强大的文本分析工具,awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理.awk语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,awk抽取信息后,才能进行其他文本操作. 使用方法 awk '{pattern+action} {filename}' pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令. 例子1:读取指定列的内容.(last -n:列出最近登陆系统的n个用户的信息) [

sed及awk命令的使用

sed命令 sed是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用,功能不同凡响.处理时,把当前处理的行存储在临时缓冲区中,称为"模式空间"(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕.接着处理下一行,这样不断重复,直到文件末尾.文件内容并没有 改变,除非你使用重定向存储输出.Sed主要用来自动编辑一个或多个文件:简化对文件的反复操作:编写转换程序等. 命令格式 sed [options] 'comman

awk经典,有这一篇就够了

copy from http://blog.chinaunix.net/uid/11172773.html 1          前言 awk是Unix环境下一种非常好的语言,适合于文本处理和报表生成,它还有许多精心设计的特性,允许进行特殊技巧程序设计.对于短消息来说,比如处理话单文件,使用awk就非常方便,鉴于测试组大部分人对awk并不熟悉,因此仅以本文作一个提纲挈领的介绍,希望对初学者迅速掌握awk有所帮助. 2          第一部分:入门 2.1    第一个awk程序 所有的编程书

AWK详细用法

awk非常的优秀,运行效率高,而且代码简单,对格式化的文本处理能力超强.基本上grep和sed能干的活awk全部都能干,而且干得更好. 先来一个很爽的例子:文件a,统计文件a的第一列中是浮点数的行的浮点数的平均值.用awk来实现只需要一句话就可以搞定(当然,这个东东用python也可以很轻松的实现,只是无论如何都得新建一个文件:别妄想用bash shell来做,那可是浮点数!!!)$cat a1.021 331#.ll   442.53 6ss    7awk 'BEGIN{total = 0;

awk练习总结

>>> >>>awk是个优秀文本处理工具,可以说是一门程序设计语言.下面是awk内置变量. 一.内置变量表 属性 说明 $0 当前记录(作为单个变量) $1~$n 当前记录的第n个字段,字段间由FS分隔 FS 输入字段分隔符 默认是空格 NF 当前记录中的字段个数,就是有多少列 NR 已经读出的记录数,就是行号,从1开始 RS 输入的记录他隔符默 认为换行符 OFS 输出字段分隔符 默认也是空格 ORS 输出的记录分隔符,默认为换行符 ARGC 命令行参数个数 ARGV

awk程序设计语言之-awk基础

awk程序设计语言之-awk基础 1 http://man.linuxde.net/ 2 7 8 常用工具命令之awk命令 9 awk是一种编程语言,用于在Linux/Unix下对文本和数据处理.数据可以来自标准输入(stdin).一个或多个文件,或其他命令的输出.它支持用户自定义函数和动态正则表达式 10 等先进功能,是Linux/unix下的一个强大编程工具.它在命令行中使用,但更多是作为脚本来使用,awk有很多内建功能,比如数组.函数等,这是它和c语言的相同之处,灵活性 11 是awk最大

sed和awk等方法实现列转成行

之前整理了一部分grep.sed和awk的文章,当然只是很基础的东西,平时我遇到的问题会把它们整理到一起,然后对比分析,这样印象会更深刻. [[email protected] ~]# cat file 1 2 3 4 5 6 7 8 9 10 11 先把列转成行,写了5方法: 1.xargs实现 [[email protected] ~]# cat file |xargs 1 2 3 4 5 6 7 8 9 10 11 2.tr实现,需要echo换行 [[email protected] ~]

awk 学习笔记

awk 使用教程 awk - pattern-directed scanning and processing language (模式定位 扫描和处理语言) Awk scans each input file for lines that match any of a set of patterns specified literally in prog or in one or more files specified as -f progfile. With each pat- tern

(转载)(收藏)Awk学习详细文档

awk命令 本文索引 [隐藏] awk命令格式和选项 awk模式和操作 模式 操作 awk脚本基本结构 awk的工作原理 awk内置变量(预定义变量) 将外部变量值传递给awk awk运算与判断 算术运算符 赋值运算符 逻辑运算符 正则运算符 关系运算符 其它运算符 运算级优先级表 awk高级输入输出 读取下一条记录 简单地读取一条记录 关闭文件 输出到一个文件 设置字段定界符 流程控制语句 条件判断语句 循环语句 while语句 for循环 do循环 其他语句 数组应用 数组的定义 数组相关函