awk

最后更新: 2024-05-22 06:31:54 +0800 +0800
tags: Awk | Gnu | Linux
原文以英文撰写。您正在阅读AI翻译版本。

awk 以记录流的形式转换文本。每条记录都会按照有序的模式-动作规则进行测试, 因此该语言适合生成报告、执行验证和进行小型数据转换。POSIX awk 广泛可用; GNU awk(gawk)增加了脚本需要显式声明的功能。

记录、字段和计数器 #

RS 分隔输入记录,默认为换行符。FS 分隔字段;其默认行为会特殊处理连续的空格和制表符。 $0 是完整记录,$1 到 $NF 是字段,NF 是字段数量。 NR 统计所有输入中的记录,而 FNR 对每个输入文件重新开始计数。

sh
awk -F ':' '$3 >= 1000 { print $1, $6 }' /etc/passwd
awk -v limit=10 'NF > limit { print FILENAME ":" FNR }' input

生成结构化结果时,应显式设置输出分隔符:

awk
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 在最后一条记录之后运行。

awk
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() 修改所有匹配。

sh
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 数据,而不是将其插入程序源码:

sh
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 上阅读或评论(发表评论需要登录)