awk 以记录流的形式转换文本。每条记录都会按照有序的模式-动作规则进行测试,
因此该语言适合生成报告、执行验证和进行小型数据转换。POSIX awk 广泛可用;
GNU awk(gawk)增加了脚本需要显式声明的功能。
记录、字段和计数器 #
RS 分隔输入记录,默认为换行符。FS 分隔字段;其默认行为会特殊处理连续的空格和制表符。
$0 是完整记录,$1 到 $NF 是字段,NF 是字段数量。
NR 统计所有输入中的记录,而 FNR 对每个输入文件重新开始计数。
awk -F ':' '$3 >= 1000 { print $1, $6 }' /etc/passwd
awk -v limit=10 'NF > limit { print FILENAME ":" FNR }' input生成结构化结果时,应显式设置输出分隔符:
BEGIN { FS = OFS = "," }
NF >= 3 { total += $3 }
END { print "total", total }GNU awk 将多字符 RS 视为正则表达式。可移植的 awk 要求记录分隔符为单个字符,
因此处理以 NUL 分隔的名称时应显式要求 gawk,例如 gawk -v RS='\0'。
编写模式-动作程序 #
规则的形式为 pattern { action }。/error/ 这样的正则表达式会测试 $0;
表达式会根据 awk 的真值规则进行测试;省略模式则匹配每条记录。
BEGIN 在输入前运行,END 在最后一条记录之后运行。
BEGIN { FS = ":" }
$7 ~ /nologin$/ { next }
{ users[$1] = $6 }
END {
for (name in users)
print name, users[name]
}关联数组的键是字符串,for (key in array) 没有可移植的迭代顺序。
需要确定性输出时,应在外部排序,或使用有文档说明的 GNU awk 排序功能。
值和正则表达式 #
awk 值具有字符串和数值形式。上下文决定转换方式:
total += $3 需要数字,而连接操作需要字符串。
应在依赖转换前验证输入,因为非数字字符串在数值上下文中会转换为零。
正则表达式使用 POSIX 扩展正则表达式语法。~ 和 !~ 测试值;
match()、sub()、gsub() 和 split() 在动作中执行操作。
sub() 修改第一个匹配,gsub() 修改所有匹配。
awk '
/^[[:space:]]*#/ || NF == 0 { next }
$2 ~ /^[0-9]+$/ { count[$1] += $2 }
END { for (key in count) print key, count[key] }
' metrics.txt安全地调用 awk
#
将程序放在单引号中,使 shell 不会在 awk 接收前展开 $1、反斜杠或 glob 字符。
使用 -v 传递 shell 数据,而不是将其插入程序源码:
awk -v prefix="$prefix" '$1 == prefix { print $0 }' input
awk -f report.awk -- --filename-starting-with-dash在支持 -- 的实现中,该选项会结束 awk 的选项处理;当输入名称可能以 - 开头时应使用它。
将 -v 数据视为数据,而不是 awk 源码。对于不受信任的 CSV,应使用支持 CSV 的解析器或 GNU awk
有文档说明的 --csv 模式,因为 FS="," 不会实现 CSV 引号规则。
评论
在 GitHub 上阅读或评论(发表评论需要登录)