AWK使用.md
AWK使用
转载:20分钟降服awk
awk是unix下的文本处理工具,功能复杂灵活,可以实现诸如cat, grep, cut, head, sed, wc 等所有文本处理命令的功能。相应的,awk的学习成本也是比较高的。我一直是边用边查边学。网是的内容比较零散,总有一种见树不见林的感觉。今天读到了Awk in 20 Minutes一文,让人拍案教绝。此文从宏观角度分析了awk程序的概念、结构和工作方式,用20%篇幅讲清楚了awk的80%的功能,让人不禁感概想见恨晚。现择其要点分享给大家。
首先,awk脚本的结构是这样的:
# comment
Pattern1 { ACTIONS; }
# comment
Pattern2 { ACTIONS; }
awk从标准输入逐行读取内容,然后使用不同的模式(Pattern)进行匹配,如果匹配成功,则会执行对应大括号内的动作(Action)。这就是awk的执行模型。读取、匹配、执行,就这么简单,所用复杂的功能都是在这个模型之上衍生出来的。
在说模式和动作之间,先简单提一下变量。
awk的变量有三种:字符串、数字和字典。字符串和数字可以相互转换。
变量无需声明,可直接使用,如{a=1}
。数字变量可以执行数学运算,如{a+=1}
。字典赋值使用方括号,如{a[hi]=1}
。
awk内置一组特殊变量,分别是$0, $1, ..., $n
。它们都以美元符号开头,所面跟一个数字。它们的值取自 awk 读入的文体内容。比如 awk 读入的一行内容为a b c
,那么对应的$1
的内容为a
,$2
和$3
的内容分别为b
和c
;$0
比较特别,其内容是读入的整行即a b c
。 awk默认使用一个或多个空白字符切割字段。
awk还有另一拨不常用的高级内置变量,在有些场景下有奇效,大家留点印像就好了。
BEGIN { # 用户可以修改
FS = ","; # 内容分割符
RS = "\n"; # 行(记录)分割符
OFS = " "; # 输出内容分割符
ORS = "\n"; # 输出行(记录)分割符
}
{ # 用户无法修改
NF # 当前行字段(列)数量
NR # 当前行的行数
ARGV / ARGC # 脚本参数
}
有了变量基础,我们再说模式。模式有三类:正则模式、布尔模式和特殊模式。
典型的正则模式有
/admin/ { ... } # 匹配包含 admin 的内容
/^admin/ { ... } # 匹配 admin 开头的内容
/admin$/ { ... } # 匹配 admin 结尾的内容
/^[0-9.]+ / { ... } # 匹配数字开头的内容
/(POST|PUT|DELETE)/ # 匹配包含部分 http 请求的内容
对于更简单的场景,你还可以直接使用变量比较运算来过滤内容,比如
$1 == 200 { ... } # 匹配状态码为 200 的请求日志(假设第一列为 http 状态码)
$1 >= 500 { ... } # 匹配 5xx 请求
$1 != 200 { ... } # 匹配非 200 请求
你还可以使用布尔表达式将这些匹配模式组合起来,比如
/admin/ || $1 >= 500 # 匹配 admin 接口的 5xx 错误
除此之外,awk还支持两种特殊的模式:BEGIN和END,分别在脚本开始之前和结束之后触发。比如awk 'BEGIN{c=0}/admin/{c+=1}END{print c}'
会在结束的时候输出含有admin日志的行数。
最后说一下动作。简单的动作有
{ a=$1; b=$0 } # 变量赋值
{ c[$1] = $2 } # 字典赋值
{ exit; } # 结束程序,很少使用
{ next; } # 跳过当前行
awk还支持条件分支和循环结构,如下
{ if ($3 >= 500) { ACTION }
else if ($3 >= 400) { ACTION }
else { ACTION }
}
{ for (i=1; i<x; i++) { ACTION } }
{ for (item in c) { ACTION } }
好了,讲完了。最后给几个示例
统计 user 接口单ip的请求数量超过10次的ip
/user/ { ip=$1; ip_count[ip]++ }
END{ for (ip in ip_count) { if (ip_count[ip] > 10) { print ip, ip_count[ip] } } }
请理 ubuntu 的 rc 配置包
dpkg -l|awk '/^rc/ {print $2}'|xargs aptitude purge -y
时间差不多了,你学会了吗?