awk用法详解
awk是一个非常强大的工具,其核心是“模式-动作”对。掌握了基本结构、内置变量和函数后,你可以用它高效地完成各种文本处理、数据提取和报告生成任务。对于更复杂的逻辑,可以编写在BEGIN和END块中。awk 'BEGIN { /* 初始化 */ } /pattern/ { /* 处理每一行 */ } END { /* 收尾工作 */ }' input.txt。
awk 是一种功能强大的文本处理工具和编程语言,尤其适用于处理结构化文本数据(如日志、CSV文件等)。它的名字来源于其三位创始人的姓氏首字母:Aho、Weinberger 和 Kernighan。
核心概念
awk 的基本思想是:逐行扫描文件(或输入流),根据给定的“模式(Pattern)”执行对应的“动作(Action)”。
其基本语法结构为:
awk 'pattern { action }' input_file
- 如果省略
pattern,则对每一行都执行action。 - 如果省略
{ action },则默认动作是打印匹配pattern的行(即{ print $0 })。
1. 基本用法和常用选项
| 选项 | 含义 |
|---|---|
-F fs |
指定输入字段分隔符(Field Separator),默认为空格和制表符。例如 -F ':' 或 -F "," |
-v var=value |
定义一个变量并赋值,可以在 awk 脚本中使用。 |
-f scriptfile |
从文件而不是命令行中读取 awk 脚本。 |
示例:
# 打印 /etc/passwd 文件的第一列(用户名)和第三列(用户ID)
awk -F ':' '{ print $1, $3 }' /etc/passwd
# 使用多个分隔符(先使用空格或逗号进行分割)
awk -F '[ ,]' '{ print $1, $2 }' file.txt
2. awk 程序结构:Pattern 和 Action
一个 awk 程序通常由一系列 pattern { action } 语句组成。
a) 特殊的 Pattern
awk 有一些特殊的 pattern,它们不是正则表达式,而是关键字:
| Pattern | 含义 |
|---|---|
BEGIN |
在处理任何输入行之前执行一次。常用于初始化变量、打印表头。 |
END |
在处理完所有输入行之后执行一次。常用于汇总和输出最终结果。 |
NR == n |
仅处理第 n 行(NR 是内置变量,代表当前行号)。 |
NF > n |
仅处理字段数(列数)大于 n 的行(NF 是内置变量,代表当前行的字段数)。 |
示例:
# 打印前加上表头,最后加上结束语
awk -F ':' 'BEGIN { print "User\tUID" } { print $1 "\t" $3 } END { print "Processing complete." }' /etc/passwd
# 只处理第5到10行
awk 'NR>=5 && NR<=10 { print $0 }' file.txt
b) 常见的 Pattern 类型
-
正则表达式 Pattern:
/regex/# 打印包含 "error" 或 "Error" 的行(忽略大小写) awk '/[Ee]rror/ { print $0 }' logfile.log # 另一种写法:使用 ~ 操作符 awk 'tolower($0) ~ /error/ { print }' logfile.log -
比较表达式 Pattern:使用比较运算符(
==,!=,>,<,>=,<=)# 打印第三列大于1000的行 awk -F ':' '$3 > 1000 { print $1 }' /etc/passwd -
范围 Pattern:
pattern1, pattern2# 打印从包含 "START" 的行到包含 "END" 的行之间的所有内容 awk '/START/, /END/ { print }' file.txt -
组合 Pattern:使用逻辑运算符
&&(与),||(或),!(非)# 打印第一列为 "root" 且第三列为0的行 awk -F ':' '$1 == "root" && $3 == 0' /etc/passwd
3. 内置变量
awk 提供了许多有用的内置变量:
| 变量 | 含义 |
|---|---|
$0 |
当前整行的内容。 |
$1, $2, ... $NF |
当前行的第1、第2、直到最后一个字段。 |
NF (Number of Fields) |
当前行的字段总数。$NF 代表最后一个字段。 |
NR (Number of Records) |
当前处理的行号(累计 across files)。 |
FNR (File Number of Records) |
当前文件中的行号(对每个文件重置为1)。 |
FS (Field Separator) |
输入字段分隔符,默认为空格。可通过 -F 选项设置。 |
OFS (Output Field Separator) |
输出字段分隔符,默认为空格。例如 awk -v OFS="," '{print $1,$2}'。 |
RS (Record Separator) |
输入记录(行)分隔符,默认为换行符 \n。 |
ORS (Output Record Separator) |
输出记录(行)分隔符,默认为换行符 \n。 |
FILENAME |
当前正在处理的文件名。 |
示例:
# 打印每行的行号和最后一个字段
awk '{ print NR, $NF }' file.txt
# 打印文件总行数
awk 'END { print NR }' file.txt
# 打印字段数大于2的行的第一个字段
awk 'NF > 2 { print $1 }' file.txt
4. 动作(Action)和函数
动作是在 {} 中执行的语句块,最常见的动作是 print 和 printf。
a) print 和 printf
print:自动在输出项之间加上OFS,最后加上ORS。printf:格式化输出,类似于 C 语言的printf。
# print 示例
awk '{ print "User:", $1, "UID:", $3 }' /etc/passwd
# printf 示例(更精确控制格式)
awk -F ':' '{ printf "Username: %-15s UID: %d\n", $1, $3 }' /etc/passwd
# %-15s: 左对齐,占15个字符的字符串
# %d: 十进制整数
# \n: 换行
b) 算术和字符串操作
awk 内置支持变量和算术运算。
# 计算第一列数字的总和
awk '{ sum += $1 } END { print sum }' numbers.txt
# 字符串连接直接使用空格即可
awk '{ print $1 "-" $2 }' file.txt # 输出 first-second
c) 流程控制
awk 支持 if、else、while、for 等流程控制语句,语法类似 C 语言。
# 条件判断
awk '{ if ($3 > 1000) print $1 " is a user"; else print $1 " is a system account" }' /etc/passwd
# 循环
awk '{ for (i=1; i<=NF; i++) print "Field", i, ":", $i }' file.txt
d) 内置函数
awk 提供了丰富的内置函数。
- 数学函数:
sin(),cos(),sqrt(),log(),int() - 字符串函数:
length(str): 返回字符串长度。substr(str, start, len): 提取子串。index(str, substr): 查找子串位置。split(str, arr, fs): 将字符串分割到数组。gsub(rgex, repl, str): 全局替换。tolower(str),toupper(str): 转换大小写。
# 将第一列转换为大写
awk '{ print toupper($1) }' file.txt
# 替换所有的 "old" 为 "new"
awk '{ gsub(/old/, "new"); print }' file.txt
5. 高级用法:数组
awk 支持关联数组(字典或哈希表),索引可以是数字或字符串。
# 统计第一列每个值出现的次数
awk '{ count[$1]++ } END { for (item in count) print item, count[item] }' data.txt
# 计算每个用户的进程总数(例如来自 `ps aux` 的输出)
ps aux | awk '{ user[$1]++ } END { for (u in user) print u, user[u] }'
6. 综合示例
假设我们有一个名为 sales.txt 的文件,内容如下:
Alice,100,2023-10-25
Bob,150,2023-10-25
Alice,200,2023-10-26
Charlie,50,2023-10-26
Bob,300,2023-10-27
任务:计算每个人的总销售额。
awk -F ',' '{ sales[$1] += $2 } END { for (name in sales) print name, sales[name] }' sales.txt
输出可能为:
Alice 300
Bob 450
Charlie 50
总结
awk 是一个非常强大的工具,其核心是 “模式-动作” 对。掌握了基本结构、内置变量和函数后,你可以用它高效地完成各种文本处理、数据提取和报告生成任务。对于更复杂的逻辑,可以编写在 BEGIN 和 END 块中。
对于日常使用,记住这个“万能”结构会非常有帮助:
awk 'BEGIN { /* 初始化 */ } /pattern/ { /* 处理每一行 */ } END { /* 收尾工作 */ }' input.txt
更多推荐

所有评论(0)