2 分钟阅读 次阅读

awk 是一种强大的文本处理编程语言,特别适合处理结构化文本数据(如日志、CSV、表格数据等)。它以为单位处理文本,并可以按字段进行操作。

基本语法结构

awk 'pattern { action }' file

command | awk 'pattern { action }'
  • pattern:匹配模式(可选)
  • action:执行的操作(用花括号 {} 括起来)
  • file:要处理的文件

常用命令行选项

选项 说明
-F fs 设置字段分隔符
-v var=value 定义变量
-f scriptfile 从文件读取 awk 脚本
-W 启用特定扩展功能

核心概念

1. 字段和记录

  • 记录 (Record):默认以换行符分隔,一行就是一个记录
  • 字段 (Field):默认以空格或制表符分隔,每个单词是一个字段
  • $0:整个当前行
  • $1, $2, $3…:第 1、2、3…个字段
  • NF:当前行的字段数量
  • NR:当前处理的行号(从 1 开始)

常用内置变量

变量 说明 示例
$0 整行内容 {print $0}
$n 第 n 个字段 {print $1, $3}
NF 字段数量 {print "字段数:", NF}
NR 当前行号 {print "行号:", NR}
FS 输入字段分隔符 BEGIN{FS=":"}
OFS 输出字段分隔符 BEGIN{OFS="-"}
RS 输入记录分隔符  
ORS 输出记录分隔符  

基本用法示例

1. 打印整行

awk '{print $0}' file.txt      # 打印所有行
awk '{print}' file.txt         # 同上,print默认打印$0

2. 打印特定字段

awk '{print $1}' file.txt      # 打印每行第1个字段
awk '{print $1, $3}' file.txt  # 打印第1和第3个字段
awk '{print $NF}' file.txt     # 打印最后一个字段

3. 设置字段分隔符

# 使用-F选项
awk -F':' '{print $1}' /etc/passwd
awk -F',' '{print $2}' data.csv

# 在BEGIN块中设置
awk 'BEGIN{FS=":"} {print $1}' file.txt
awk 'BEGIN{FS="[;,]"} {print $1}' file.txt  # 多个分隔符

4. 条件筛选

# 打印包含"error"的行
awk '/error/ {print}' log.txt

# 打印不包含"error"的行
awk '!/error/ {print}' log.txt

# 第3个字段大于100的行
awk '$3 > 100 {print}' data.txt

# 第1个字段等于"John"的行
awk '$1 == "John" {print}' file.txt

# 多条件组合
awk '$1 == "John" && $3 > 100 {print}' file.txt
awk '$1 == "John" || $2 == "Smith" {print}' file.txt

5. BEGIN 和 END 块

# 在开始前执行
awk 'BEGIN{print "开始处理..."} {print $0}' file.txt

# 在结束后执行
awk '{print $0} END{print "处理完成"}' file.txt

# 组合使用
awk 'BEGIN{FS=":"; OFS="\t"} {print $1, $3} END{print "总计行数:", NR}' file.txt

常用操作

1. 计算和统计

# 求第2列的和
awk '{sum += $2} END{print "总和:", sum}' data.txt

# 求平均值
awk '{sum += $2; count++} END{print "平均值:", sum/count}' data.txt

# 最大值
awk 'NR==1 {max=$2} $2>max {max=$2} END{print "最大值:", max}' data.txt

2. 格式化输出

# 使用printf格式化输出
awk '{printf "姓名:%-10s 年龄:%3d\n", $1, $2}' data.txt

3. 字符串操作

# 获取字符串长度
awk '{print length($1)}' file.txt

# 截取子串
awk '{print substr($1, 1, 3)}' file.txt  # 取前3个字符

# 替换字符串
awk '{gsub(/old/, "new", $0); print}' file.txt

实际应用示例

示例 1:处理/etc/passwd

# 提取用户名和shell
awk -F: '{print $1, $7}' /etc/passwd

# 查找bash用户
awk -F: '$7 ~ /bash/ {print $1}' /etc/passwd

示例 2:统计日志

# 统计IP访问次数
awk '{ip[$1]++} END{for(i in ip) print i, ip[i]}' access.log

# 按访问次数排序
awk '{ip[$1]++} END{for(i in ip) print i, ip[i]}' access.log | sort -k2 -nr

示例 3:数据转换

# CSV转TSV
awk 'BEGIN{FS=","; OFS="\t"} {print $1, $2, $3}' data.csv

# 重组数据
awk '{print $3, $1, $2}' file.txt

示例 4:条件判断

# 成绩分类
awk '{
  if($2 >= 90) grade="A";
  else if($2 >= 80) grade="B";
  else if($2 >= 70) grade="C";
  else grade="D";
  print $1, $2, grade
}' scores.txt

实用技巧

1. 多个命令

awk '{
  print $1
  print "---"
}' file.txt

2. 内置函数

awk '{print toupper($1)}' file.txt      # 转大写
awk '{print tolower($1)}' file.txt      # 转小写

3. 范围模式

# 打印从匹配"start"到匹配"end"的所有行
awk '/start/,/end/' file.txt

4. 变量使用

awk '{total += $2; count++} END{avg=total/count; print "平均值:", avg}' data.txt

留下评论