41·Shell 脚本进阶进阶

awk 文本处理基础

awktext-processing

第41课 - awk 文本处理基础

学习目标

通过本课学习,你将能够:

  1. 理解 awk 命令的基本语法和工作原理
  2. 使用 awk 处理结构化文本文件中的字段
  3. 掌握 awk 的核心内置变量和常用动作语句
  4. 运用 awk 结合条件模式进行简单文本过滤与格式化输出

核心概念

1. 什么是 awk?

awk 是 Linux 系统中一个强大的文本和数据处理工具。你可以把它想象成一个针对文本文件的“编程语言”或“表格处理器”。它能按行读取输入,根据你指定的规则(模式)对每一行进行匹配,并执行相应的动作(如打印、计算)。它特别擅长处理结构化的文本数据,比如日志文件、CSV文件、/etc/passwd 等。

2. awk 的基本语法

awk 的基本结构非常清晰:

awk [选项] ‘模式 {动作}’ 输入文件
  • 模式 (Pattern): 决定对哪些行执行动作。可以是正则表达式、条件判断(如 $3 > 100)或特殊模式(如 BEGIN, END)。如果省略模式,则对每一行都执行动作。
  • 动作 (Action): 由花括号 {} 包裹的一系列命令,告诉 awk 对匹配的行做什么。最常用的动作是 print
  • 输入文件: awk 要处理的文件。也可以通过管道接收来自其他命令的输入。

3. 字段与记录

awk 将输入文本视为记录 (Record)字段 (Field)

  • 记录: 默认以换行符 \n 分隔,所以一行就是一个记录
  • 字段: 默认以空格或制表符分隔。每个记录被分割成多个字段。
    • $0: 代表整个当前记录(即整行)。
    • $1: 代表当前记录的第一个字段。
    • $2: 代表第二个字段,以此类推。
    • $NF: 代表最后一个字段(NF 是一个内置变量,表示当前记录的字段总数)。

你可以通过 -F 选项自定义字段分隔符。

4. 内置变量

awk 提供了一些有用的内置变量,无需定义即可使用:

  • NR: 当前已读取的记录数(行号)。
  • NF: 当前记录的字段总数。
  • FS: 输入字段分隔符(默认空格)。
  • OFS: 输出字段分隔符(默认空格)。

代码示例

示例1:基本字段提取

处理 /etc/passwd 文件,该文件以冒号 : 分隔。提取并打印用户名(第1列)和用户ID(第3列)。

# 使用 -F 指定输入分隔符为冒号
# 打印第一个字段($1)和第三个字段($3),并用自定义分隔符连接
awk -F: ‘{print $1, $3}’ /etc/passwd

预期输出(部分)

root 0
daemon 1
bin 2
...

示例2:添加表头和条件过滤

在上一个例子的基础上,添加表头,并只打印 UID 大于 1000 的普通用户。

# BEGIN 模式在读取任何输入前执行一次,这里用于打印表头
# 之后的模式 `$3 > 1000` 是一个条件,只有当第三个字段(UID)大于1000时,才执行后面的 print 动作
awk -F: ‘BEGIN {print “Username\tUserID”} $3 > 1000 {print $1, “\t”, $3}’ /etc/passwd

预期输出(部分)

Username        UserID
ubuntu   1000
cloud    1001

示例3:使用内置变量和格式化输出

统计一个文件有多少行(记录),并打印每行的行号、字段数和内容。

# 创建一个测试文件
echo -e “Hello World\nThis is a test\nAwk is cool” > test.txt

# 使用 awk 处理
# NR 是行号,NF 是当前行的字段数,$0 是整行内容
# printf 用于格式化输出,类似C语言
awk ‘{printf “Line %d has %d fields: %s\n”, NR, NF, $0}’ test.txt

预期输出

Line 1 has 2 fields: Hello World
Line 2 has 4 fields: This is a test
Line 3 has 3 fields: Awk is cool

实践练习

练习1:基础提取

要求:使用 awk/etc/passwd 文件中提取并打印用户名用户主目录(分别是第1列和第6列),用 - 连接。分隔符是冒号。 预期输出(开头几行):

root - /root
daemon - /usr/sbin
bin - /bin

练习2:条件过滤

要求:从 ls -l 命令的输出中,找出文件大小大于1000字节的文件,并只打印文件名(最后一列)和大小(第5列)。ls -l 的默认输出格式中,第5列是大小,最后一列是文件名。 提示:先使用 ls -l 查看输出格式,理解哪些列是你需要的。 预期输出示例(取决于你的目录内容):

some_large_file.log 2048

练习3:简单计算与格式化

要求:给定一个包含商品名称和价格的简单数据文件 prices.txt(你可以自己创建,例如包含三行:Apple 1.5Banana 0.8Orange 2.0)。使用 awk 计算所有商品价格的总和,并在处理完所有行后(使用 END 模式)打印出 “Total: [总和]”。 预期输出

Total: 4.3

常见错误

  1. 忘记使用单引号awk 的程序体(模式和动作)必须用单引号 ' ' 包裹,以防止 Shell 在将其传递给 awk 之前进行解释。例如,awk {print $1} 是错误的,应为 awk '{print $1}'
  2. 字段分隔符使用错误:当数据分隔符不是空格时,忘记使用 -F 选项指定。或者,在使用 -F 时,错误地将分隔符放在了动作语句里。
  3. 混淆字段变量:在动作语句中,错误地将 $ 用在了变量名前(如 print $NR),而 NR 本身就是一个变量,不需要 $$0, $1...$NF 是特殊的字段变量。
  4. printprintf 的混淆print 会自动在输出末尾添加换行符,并用输出字段分隔符(OFS,默认为空格)分隔参数。printf 提供更精确的格式化控制,但需要手动添加换行符 \n

小结

本课我们学习了 awk 文本处理工具的基础知识:

  • 核心结构awk 的工作流程是 模式 {动作}。模式决定对哪行操作,动作决定做什么。
  • 字段处理:通过 $1, $2 ... $NF 访问行内的不同字段,用 -F 指定分隔符。
  • 内置变量NR(行号)、NF(字段数)等是自动化处理和统计的强大帮手。
  • 模式应用BEGINEND 模式允许你在处理开始前和结束后执行动作,实现表头添加、汇总计算等功能。

awk 的功能远不止于此,它是 Shell 脚本中进行复杂文本处理和报告生成的利器。掌握这些基础后,我们将进入下一课,学习 awk 的高级用法,如数组、字符串函数和更多内置函数。现在,请务必完成练习,动手实践是掌握 awk 的最佳途径!

练习编辑器

rust
Loading...

继续学习

完成本课后,建议继续学习下一课「awk 高级用法与数组」 以巩固所学知识。