AWK
基本语法范例
awk '{print $0}' file1 ... file2 ...awk -f check.awk file1 ... file2 ...
稍微复杂一点的建议用后面的这个方式。
假定我们有个access.log日志,以 ### 作为字段的分隔符,包含时间/请求IP/响应编码/请求url
1
2
2018-12-11 11:11:11 #### 44.44.44.44 ### 200 ### /mod1/url1
2018-12-11 12:12:12 #### 55.55.55.55 ### 200 ### /mod2/url2
可以用这个awk脚本count-by-ip.awk来根据IP来源做请求量统计
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# awk -f count-by-ip.awk access.log
BEGIN {
FS = ' ### '
}
{
arr[$2]++;
}
END {
for (tag in arr){
print tag, arr[tag]
}
}
- 复杂一点的业务逻辑,建议在开头写注释。如果调用方式也特殊,建议注释里加上调用范例。
- awk中
$0表示这一行,$1...$n表示各个field - BEGIN中做初始化准备工作,一般适合在这里做环境变量设置;
- END中做收尾工作,一般在这里输出统计结果;
进一步的小技巧
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# awk -f count-by-ip.awk access.log
BEGIN {
FS = ' ### '
}
{
# records before "2018-12-11 13:00:00"
if ($1 > "2018-12-11 13:00:00") exit;
# skip wrong line.
if (!$2) next;
arr[$2]++;
}
END {
for (tag in arr){
print tag, arr[tag]
}
}
next语句结束当前这行数据的处理,继续下一行,相当于continue;这个是一个特别好的编程习惯;exit语句将结束awk的行处理流程,相当于break,如果有END模块将执行;
案例
使用 - 集成管道操作的输入
1
2
3
4
5
6
7
8
9
10
$ echo 123 | tee 1.log
123
$ echo '456' | awk '{print $0}' 1.log -
123
456
$ echo '456' | awk '{print $0}' - 1.log
456
123
利用NR和FNR做【引入新列】
- 需求
将其中一个文件中的列“引入到另外一个文件中”,例如:- id->name 关系表,
id2name.lst1 2
zhangsan 张三 lisi 李四
- 数据条目,有id字段,
record.lst1 2 3
zhangsan 100 lisi 99 wangwu 90
需求是将name加入到数据中。
- id->name 关系表,
- 解决方案
convert.awk```awk -f convert.awk id2name.lst record.lst
{ if (NR == FNR) { map[$1] = $2; next; }
print $1, map[$1] ? map[$1] : “蒙面人” , $2 }
1
2
3
4
5
6
7
3. 结果验证
```shell
$ awk -f convert.awk id2name.lst record.lst
zhangsan 张三 100
lisi 李四 99
wangwu 蒙面人 90
- 扩展
留下评论