“ awk 一般用于比较规范的文件处理,是 sed 命令的补充。”
01—基本概念
awk 脚本的流程控制,主要包含三部分,第 1, 3 部分可忽略。
输入数据前 BEGIN{}
,数据处理前做一些预处理工作。主循环 {}
。所有文件读取完成 END {}
。
每行称作 awk 的记录,默认使用空格、制表符分开,每个分开的单词叫做字段。
在 awk 中使用使用 $1 $2 ... $n
表示每一个字段($0
表示整行)。
可以用 -F
指定分隔符,分隔符也可以使用正则表达式。
awk -F ',' '{print $1,$2,$3}' filename
示例:
[/tmp]$ cat a.log
a,b,c,d,e
1,2,3,4
a,2,c
# 正则过滤,然后给每行一个编号,打印第二列
[/tmp]$ awk -F',' '/^[a-z]/{print x++,$2}' a.log
0 b
1 2
系统变量
- FS:输入字段分隔符,等同于 -F
- OFS:输出字段分隔符
- RS:记录分隔符,默认是换行(\n)
- NR 和 FNR 显示行号
- NF 字段数量
# 更改输入和输出分隔符
[/tmp]$ awk 'BEGIN{FS=",";OFS="-"}{print $1,$2,$3}' a.log
a-b-c
1-2-3
a-2-c
# 更改记录分隔父
[/tmp]$ awk 'BEGIN{RS=","}{print $1,$2,$3}' a.log
a
b
c
d
e 1
2
3
4 a
2
c
# 显示行号 FNR 多个文件会重新计数
[/tmp]$ awk '{print NR,$0}' a.log
1 a,b,c,d,e
2 1,2,3,4
3 a,2,c
[/tmp]$ awk -F, '{print NF,$0}' a.log
5 a,b,c,d,e
4 1,2,3,4
3 a,2,c
02—条件和循环
这里的条件和循环跟编程语言的格式差不多。
条件
语法格式:
if( expression ) statement [ else statement ]
示例:grades.log 中存放的第一列学生名,后面每列是成绩。
[/tmp]$ cat grades.log
user0 66 98 89 62 71
user1 63 93 70 93 85
user2 92 92 82 79 91
user3 91 77 83 63 74
user4 88 99 87 99 67
# if 内多个处理语句可以用 {} 括起来
[/tmp]$ awk '{if($2>80) print $1}' grades.log
user2
user3
user4
条件过滤
# 等同于上面 if
[/tmp]$ awk '$2>80 {print $1}' grades.log
user2
user3
user4
[/tmp]$ awk '$2>90 && $3>90' grades.log
user2 92 92 82 79 91
# // 中间是正则
[/tmp]$ awk '$1 ~ /[a-z]+1/ {print $0}' grades.log
user1 63 93 70 93 85
循环
while ( expr ) statement
do statement while ( expr )
for ( opt_expr ; opt_expr ; opt_expr ) statement
for ( var in array ) statement
示例:计算 grades.log 中每个学生的总成绩和平均成绩。
[/tmp]$ awk '{sum=0;for(i=2;i<=NF;i++) sum+=$i;print $1,sum,sum/(NF-1)}' grades.log
user0 386 77.2
user1 404 80.8
user2 436 87.2
user3 388 77.6
user4 440 88
03—数组
计算所有学生的平均值。
[/tmp]$ awk '{sum=0;for(i=2;i<=NF;i++) sum+=$i;arr[$1]=sum/(NF-1)}END{for(user in arr) sum1+=arr[user];print sum1/NR}' grades.log
82.16
命令行参数数组
这两个参数主要在写 shell 脚本比较常用,比如要给 awk 传入一些参数。
- ARGC:参数数量
- ARGV:存储参数的数组
[/tmp]$ cat arg.awk
BEGIN{
for(i=0;i<ARGC;i++)
print ARGV[i]
}
[/tmp]$ awk -f arg.awk a b c
awk
a
b
c
数组比较常用的是从 access 日志中统计请求的 ip,或者统计 url 的请求量。相比 sort + uniq -c 的统计方式,awk效率会高效很多。
04—文件拆分
比如我们要把平均成绩大于 80 分的同学单独保存到一个文件中。
[/tmp]$ awk '{sum=0;for(i=2;i<=NF;i++) sum+=$i;avg=sum/(NF-1);if(avg>80) print $1,avg > "80.log";}' grades.log
[/tmp]$ cat 80.log
user1 80.8
user2 87.2
user4 88
微信搜索 CoderMeng
关注获取更多干货文章。
大家觉得写的不错欢迎点赞
、评论
、分享
支持。
推荐阅读
你所不知道的那些sed命令