中级 awk 脚本指南

学习如何将命令构建为可执行脚本。
127 位读者喜欢这篇文章。
Coding on a computer

本文探讨了 awk 的功能,现在您已经知道如何将命令构建为可执行脚本,因此这些功能更容易使用。

逻辑运算符和条件

您可以使用逻辑运算符 **and** (写作 **&&**) 和 **or** (写作 **||**) 来增加条件的具体性。

例如,要选择并仅打印第二列中包含字符串“purple”*并且*第三列中的金额小于五的记录

$2 == "purple" && $3 < 5 {print $1}

如果一条记录在第二列中包含“purple”,但在第三列中的值大于或等于 5,则*不*会被选中。同样,如果一条记录满足第三列的要求,但在第二列中缺少“purple”,则也*不*会被选中。

下一个命令

假设您想要选择文件中金额大于或等于 8 的每个记录,并打印一个带有两个星号 ( ** ) 的匹配记录。您还想用一个星号 ( * ) 标记介于 5(含)和 8 之间的每个记录。有几种方法可以做到这一点,其中一种方法是使用 **next** 命令指示 awk 在执行操作后停止扫描并继续处理*下一个*记录。

这是一个例子

NR == 1 {
  print $0;
  next;
}

$3 >= 8 {
  printf "%s\t%s\n", $0, "**";
  next;
}

$3 >= 5 {
  printf "%s\t%s\n", $0, "*";
  next;
}

$3 < 5 {
  print $0;
}

BEGIN 命令

**BEGIN** 命令允许您在 awk 开始扫描文本文件之前打印和设置变量。 例如,您可以通过在 **BEGIN** 语句中定义输入和输出字段分隔符,在 awk 脚本中设置它们。 此示例改编了上一篇文章中的简单脚本,以用于字段由逗号而不是空格分隔的文件

#!/usr/bin/awk -f
#
# Print each record EXCEPT
# IF the first record contains "raspberry", 
# THEN replace "red" with "pi"

BEGIN {
	FS=",";
}

$1 == "raspberry" {
	gsub(/red/,"pi")
}

END 命令

与 **BEGIN** 类似,**END** 命令允许您在 awk 完成对您正在处理的文本文件的扫描后执行操作。 如果您想打印所有记录中某个值的累积结果,您只能在扫描和处理完所有记录后执行此操作。

**BEGIN** 和 **END** 命令每个只运行一次。 它们之间的所有规则在*每个记录*上运行零次或多次。 换句话说,您的大部分 awk 脚本是一个循环,它在您正在处理的文本文件的每一行中执行,**BEGIN** 和 **END** 规则除外,它们在循环之前和之后运行。

这是一个如果没有 **END** 命令就不可能实现的示例。 此脚本接受 Unix 命令 **df** 的输出值,并为每个新记录递增两个自定义变量(**used** 和 **available**)。

$1 != "tempfs" {
    used += $3;
    available += $4;
}

END {
    printf "%d GiB used\n%d GiB available\n", used/2^20, available/2^20;
}

将脚本保存为 **total.awk** 并尝试一下

df -l | awk -f total.awk

**used** 和 **available** 变量的行为类似于许多其他编程语言中的变量。 您可以随意创建它们,无需声明它们的类型,并且可以随意向它们添加值。 在循环结束时,脚本将相应列中的记录加在一起并打印总计。

数学

从目前为止的所有逻辑运算符和临时计算中您可能已经知道,awk 进行数学运算非常自然。 可以说,这使其成为您终端中非常有用的计算器。 您可以简单地使用 awk 及其特殊的 **BEGIN** 函数来避免需要文件参数,而不是努力记住 **bc** 相当不寻常的语法

$ awk 'BEGIN { print 2*21 }'
42
$ awk 'BEGIN {print 8*log(4) }'
11.0904

诚然,对于简单(和不太简单)的数学运算来说,这仍然需要大量打字,但是编写一个前端并不需要花费太多精力,这是一个供您探索的练习。


本文改编自 Hacker Public Radio(一个社区技术播客)的一集。

接下来阅读什么
标签
Seth Kenlon
Seth Kenlon 是一位 UNIX 极客、自由文化倡导者、独立多媒体艺术家和 D&D 爱好者。 他曾在电影和计算行业工作,通常同时进行。
User profile image.
Dave Morriss 是一位退休的 IT 经理,居住在苏格兰爱丁堡。 他曾在英国高等教育部门工作,为学生和教职员工提供 IT 服务。

2 条评论

文本“如果一条记录在第二列中包含“purple”,但在第三列中的值大于 5,则不会被选中。”应改为“大于或等于 5”

谢谢 Mark_Steward_1337,您说得对。 我已添加您的澄清。

Creative Commons License本作品已获得 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.