awk命令

16 阅读2分钟

awk 是 Linux/Unix 系统中功能强大的文本处理工具,擅长对数据进行格式化输出、统计分析、过滤筛选等操作。它以“行”为基本处理单位,结合内置变量、函数和自定义逻辑,能高效处理结构化数据(如日志、CSV、表格等)。以下是系统的 awk 学习指南:

一、基本语法

awk [选项] '模式 {动作}' [输入文件]
  • 选项:常用 -F(指定字段分隔符)、-v(定义变量)。

  • 模式:用于筛选符合条件的行(如行号、正则匹配、逻辑表达式)。

  • 动作:对匹配行执行的操作(如打印字段、计算、调用函数)。

二、核心概念:字段与内置变量

1. 字段分割

  • 默认以空格/制表符为分隔符,将每行拆分为字段(field),用 $1$2...$n 表示第 1 到第 n 个字段,$0 表示整行。

  • -F 选项自定义分隔符:

awk -F',' '{print $1, $3}' data.csv  # 以逗号分隔,打印第1和第3列
awk -F': ' '{print $1}' /etc/passwd  # 以": "分隔,打印用户名列

2. 内置变量

变量  说明                                                                
NF  每行的字段数(Number of Fields)                                   
NR  已处理的行号(行号从 1 开始,全局唯一)                            
FNR 各文件的行号(适用于多文件输入,每个文件独立计数)                 
FS  字段分隔符(Field Separator),默认值为空格/制表符                 
OFS 输出字段分隔符(Output Field Separator),默认值为空格             
RS  行分隔符(Record Separator),默认值为换行符 \n                  
ORS 输出行分隔符(Output Record Separator),默认值为换行符 \n       

三、基础用法:模式与动作

1. 简单打印

  • 打印所有行
awk '{print}' file.txt  # 等价于 cat file.txt
  • 打印指定字段
echo "apple,banana,cherry" | awk -F',' '{print $1, $3}'  # 输出: apple cherry

2. 按条件筛选行(模式匹配)

  • 正则匹配
awk '/error/' access.log  # 打印包含"error"的行
awk '$2 ~ /^[0-9]/' data.txt  # 打印第2字段以数字开头的行(~ 表示匹配)
  • 逻辑表达式
awk '$3 > 100' sales.csv  # 打印第3列数值大于100的行
awk '$1 == "user1" && $4 < 50' users.txt  # 同时满足两个条件的行

3. 格式化输出

  • 使用 OFS 自定义输出分隔符:
awk -F',' 'BEGIN{OFS="|"} {print $1, $2}' data.csv  # 输出字段用"|"分隔
  • 格式化字符串(类似 C 语言的 printf):
awk -F',' '{printf "姓名: %-10s 分数: %d\n", $1, $2}' scores.txt

四、流程控制与高级语法

1. 条件语句 if-else

awk -F',' '{
  if ($3 > 80) {
    print $1, "优秀"
  } else if ($3 >= 60) {
    print $1, "及格"
  } else {
    print $1, "不及格"
  }
}' scores.txt

2. 循环语句 for/while

  • 遍历字段
awk '{for (i=1; i<=NF; i++) print $i}' file.txt  # 逐行打印每个字段
  • 数值循环
awk 'BEGIN{for (i=1; i<=5; i++) sum += i; print "总和:", sum}'  # 输出: 总和: 15

3. 数组(Associative Array)

用于统计重复项或分组数据:

# 统计单词出现次数
awk '{
  for (i=1; i<=NF; i++) {
    word = $i
    count[word]++  # 数组下标为单词,值为出现次数
  }
} END{
  for (word in count) {
    print word, count[word]
  }
}' text.txt

五、特殊模式:BEGIN 和 END

  • BEGIN:在处理文件前执行(常用于初始化变量、设置分隔符)。

  • END:在处理完所有文件后执行(常用于输出统计结果)。

示例

# 计算文件行数和平均字段数
awk '
  BEGIN{
    FS=","  # 设置输入分隔符为逗号
    print "开始处理..."
  }
  {
    line_count++
    field_count += NF
  }
  END{
    avg = field_count / line_count
    print "总行数:", line_count
    print "平均字段数:", avg
  }
' data.csv

六、实战案例

1. 日志分析

  • 统计各IP的访问次数
awk '{ip[$1]++} END{for(i in ip) print i, ip[i]}' access.log
  • 提取特定时间段的日志
awk '$4 ~ /May\/2025/ {print $0}' access.log  # 提取2025年5月的日志

2. 数据统计

  • 计算销售额总和(CSV文件,第3列为金额):
awk -F',' '{sum += $3} END{print "总销售额:", sum}' sales.csv
  • 按部门分组统计人数
awk -F',' '{dept[$2]++} END{for(d in dept) print d, dept[d]}' employees.csv

3. 格式转换

  • 将 CSV 转换为 JSON
awk -F',' '
  BEGIN{
    print "["
    OFS='","'
  }
  {
    print "  {\"姓名\":\""$1"\",\"年龄\":\""$2"\",\"分数\":\""$3"\"}"
  }
  END{
    print "]"
  }
' scores.csv

七、常用技巧与注意事项

  1. 正则表达式

   - 使用 ~(匹配)或 !~(不匹配),支持扩展正则(需加 -r 选项):

awk -r '$1 ~ /^[0-9]{3}-[0-9]{4}/' phone.txt  # 匹配3位区号-4位号码
  1. 变量传递

   - 从 shell 传递变量到 awk:

threshold=80
awk -v thr=$threshold '$3 > thr {print $1}' scores.txt
  1. 多文件处理

 bash  awk 'NR==FNR {count++} END {print "文件数:", count}' file1.txt file2.txt file3.txt  

八、学习资源推荐

  1. 官方文档

   - GNU Awk 官方手册

  1. 经典教程

   - 《awk 编程入门》(在线阅读

   - Awk 简明教程

  1. 练习平台

   - awk.fishshell.com:在线调试 awk 命令。

通过大量练习 awk 的模式匹配和数据处理逻辑,能显著提升文本处理效率。结合 sedgrep 形成“文本处理三剑客”,可应对绝大多数数据处理场景! 🚀