awk用法与技巧详解

一、awk基本概念

1.1 什么是awk

awk是一种强大的文本分析工具,用于对文本文件进行逐行处理。它支持模式匹配、数据提取、计算和格式化输出等功能。

1.2 基本语法

支持下面3种写法

bash 复制代码
awk 'pattern {action}' input_file
awk -f script.awk input_file
script.awk input_file  # 需要在script.awk第一行写"#!/bin/awk -f",并赋予文件可执行权限chmod +xscript.awk 

二、awk工作原理

2.1 执行流程

  1. 读取输入文件的一行

  2. 按字段分隔符分割成字段

  3. 检查是否匹配pattern

  4. 如果匹配,执行action

  5. 重复直到文件结束

2.2 内置变量

变量 说明 示例
$0 整行内容 {print $0}
$1, $2... 第1,2...个字段 {print $1}
NF 当前行的字段数 {print NF}
NR 当前行号 {print NR}
FNR 当前文件的行号 {print FNR}
FS 输入字段分隔符 -F: 或 BEGIN{FS=":"}
OFS 输出字段分隔符 BEGIN{OFS="\t"}
RS 输入记录分隔符 BEGIN{RS="\n"}
ORS 输出记录分隔符 BEGIN{ORS="\n\n"}
FILENAME 当前文件名 {print FILENAME}

三、常用用法示例

3.1 基本打印

bash 复制代码
# 打印整行
awk '{print}' file.txt
awk '{print $0}' file.txt

# 打印第一列
awk '{print $1}' file.txt

# 打印多列
awk '{print $1, $3, $5}' file.txt

# 打印最后一列
awk '{print $NF}' file.txt

# 打印倒数第二列
awk '{print $(NF-1)}' file.txt

3.2 指定分隔符

bash 复制代码
# 指定输入分隔符
awk -F: '{print $1}' /etc/passwd
awk 'BEGIN{FS=":"} {print $1}' /etc/passwd

# 同时指定输入输出分隔符
awk -F: 'BEGIN{OFS="\t"} {print $1, $3}' /etc/passwd

# 多个分隔符
awk -F'[:,]' '{print $1, $2}' file.txt

3.3 条件筛选

bash 复制代码
# 匹配包含"error"的行
awk '/error/' log.txt

# 第三列等于"GET"
awk '$3 == "GET"' access.log

# 数值比较
awk '$4 > 100' data.txt
awk '$4 >= 100 && $4 <= 200' data.txt

# 第一列匹配正则
awk '$1 ~ /^192\.168/' log.txt

# 取反匹配
awk '!/error/' log.txt
awk '$1 !~ /^192\.168/' log.txt

3.4 BEGIN和END模式

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

# 在结束后执行
awk '{sum+=$1} END{print "总和:", sum}' numbers.txt

# 结合使用
awk 'BEGIN{FS=":"; OFS="\t"; print "用户名\tUID"} {print $1, $3} END{print "处理完成"}' /etc/passwd

四、高级用法与技巧

4.1 计算与统计

bash 复制代码
# 求和
awk '{sum+=$1} END{print sum}' numbers.txt

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

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

# 最小值
awk 'NR==1{min=$1} $1<min{min=$1} END{print "最小值:", min}' numbers.txt

# 统计行数
awk 'END{print NR}' file.txt

4.2 数组操作

bash 复制代码
# 统计词频
awk '{for(i=1;i<=NF;i++) count[$i]++} END{for(word in count) print word, count[word]}' text.txt

# 按第一列分组求和
awk '{sum[$1]+=$2} END{for(key in sum) print key, sum[key]}' data.txt

# 去重
awk '!seen[$0]++' file.txt  # 去重整行
awk '!seen[$1]++' file.txt  # 按第一列去重

4.3 字符串处理

bash 复制代码
# 字符串连接
awk '{print $1 "-" $2}' file.txt

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

# 子字符串
awk '{print substr($1, 2, 4)}' file.txt  # 从第2个字符开始取4个

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

# 匹配位置
awk '{print index($0, "target")}' file.txt

4.4 流程控制

bash 复制代码
# if语句
awk '{if($1>100) print $0}' data.txt
awk '{if($1>100) print "大"; else if($1>50) print "中"; else print "小"}' data.txt

# 三元运算符
awk '{print ($1>100 ? "高" : "低")}' data.txt

# for循环
awk '{for(i=1;i<=NF;i++) print i, $i}' file.txt
awk 'BEGIN{for(i=1;i<=5;i++) print i}'

# while循环
awk '{i=1; while(i<=NF){print $i; i++}}' file.txt

五、实用技巧集合

5.1 日志分析

bash 复制代码
# 统计HTTP状态码
awk '{status[$9]++} END{for(s in status) print s, status[s]}' access.log

# 统计IP访问量
awk '{ip[$1]++} END{for(i in ip) print i, ip[i]}' access.log | sort -k2 -nr

# 提取时间段的日志
awk '/12\/Dec\/2023:10:/,/12\/Dec\/2023:11:/' access.log

# 统计接口响应时间大于1秒的请求
awk '$NF > 1 {print $7, $NF}' access.log | sort -k2 -nr

5.2 数据格式化

bash 复制代码
# 对齐输出
awk '{printf "%-20s %10d\n", $1, $2}' data.txt

# 生成表格
awk 'BEGIN{printf "+----------------+----------+\n| 名称          | 数值     |\n+----------------+----------+"} {printf "| %-14s | %8d |\n", $1, $2} END{printf "+----------------+----------+\n"}' data.txt

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

5.3 系统管理

bash 复制代码
# 监控进程内存
ps aux | awk '$6>100000 {print $0}'

# 磁盘使用率
df -h | awk 'NR>1 && $5+0 > 80 {print "警告:", $1, "使用率:", $5}'

# 统计文件大小
ls -l | awk 'NR>1 {sum+=$5; count++} END{print "总数:", count, "总大小:", sum/1024/1024 "MB"}'

5.4 文本处理

bash 复制代码
# 提取两个标记之间的内容
awk '/START/,/END/' file.txt

# 删除空行
awk 'NF' file.txt  # 或 awk '!/^$/'

# 添加行号
awk '{print NR, $0}' file.txt

# 反转行序
awk '{lines[NR]=$0} END{for(i=NR;i>0;i--) print lines[i]}' file.txt

# 合并连续空行为一个
awk 'NF{print; blank=0} !NF{blank++; if(blank==1) print}'

六、实战示例

6.1 分析Nginx访问日志

bash 复制代码
#!/bin/bash
# 分析日志脚本

LOG_FILE="access.log"

echo "=== 访问日志分析报告 ==="
echo "1. 总访问次数:"
awk 'END{print NR}' $LOG_FILE

echo -e "\n2. 独立IP数量:"
awk '{ip[$1]++} END{print length(ip)}' $LOG_FILE

echo -e "\n3. 最活跃的10个IP:"
awk '{ip[$1]++} END{for(i in ip) print ip[i], i}' $LOG_FILE | sort -nr | head -10

echo -e "\n4. HTTP状态码统计:"
awk '{status[$9]++} END{for(s in status) printf "%-4s: %d\n", s, status[s]}' $LOG_FILE

echo -e "\n5. 最受欢迎的10个页面:"
awk '{page[$7]++} END{for(p in page) print page[p], p}' $LOG_FILE | sort -nr | head -10

6.2 数据报表生成

bash 复制代码
#!/usr/bin/awk -f
# sales_report.awk - 销售报表生成

BEGIN {
    FS=","
    OFS="\t"
    print "销售报表"
    print "=========================================="
    print "销售人员\t销售额\t提成\t总工资"
    print "------------------------------------------"
    total_sales = 0
    total_commission = 0
    total_salary = 0
}

{
    sales = $2
    commission = sales * 0.1  # 10%提成
    salary = 3000 + commission
    
    total_sales += sales
    total_commission += commission
    total_salary += salary
    
    printf "%s\t%.2f\t%.2f\t%.2f\n", $1, sales, commission, salary
}

END {
    print "------------------------------------------"
    printf "总计\t%.2f\t%.2f\t%.2f\n", total_sales, total_commission, total_salary
    print "=========================================="
}

七、性能优化技巧

预处理模式匹配

bash 复制代码
# 差的写法
awk '{if($1=="A" || $1=="B" || $1=="C") print}'

# 好的写法
awk '$1=="A" || $1=="B" || $1=="C"'
awk '$1 ~ /^(A|B|C)$/'

减少字段引用

bash 复制代码
# 差的写法
awk '{print $1, $3, $5, $7, $9}'

# 好的写法
awk '{printf "%s %s %s %s %s\n", $1, $3, $5, $7, $9}'

使用内置函数代替shell命令

bash 复制代码
# 避免调用外部命令
awk '{system("echo " $1)}'  # 慢
awk '{print $1}'           # 快

八、常见问题解答

Q1: awk与sed的区别?

  • awk:更适合处理结构化数据,支持字段操作、计算、数组

  • sed:更适合简单的文本替换、删除、插入

Q2: 如何处理大文件?

  • 使用合适的字段分隔符

  • 避免在action中调用外部命令

  • 使用next跳过不相关的行

Q3: awk可以处理二进制文件吗?

  • 不推荐,awk是文本处理工具,对于二进制文件应使用专门的工具

九、学习资源

  1. 官方文档 : man awk, info awk

  2. 经典书籍: 《sed与awk》

  3. 在线练习: 使用小文件进行测试

  4. 实践项目: 分析系统日志、处理CSV数据、生成报表

通过掌握这些用法和技巧,你可以高效地使用awk处理各种文本分析任务,大大提高工作效率。

相关推荐
Lueeee.3 小时前
正点原子 ATK-DLRK3568 开发板:按键中断 + 工作队列传参实验(完整版流程 + 功能解释)
linux
小码吃趴菜3 小时前
进程间通信 管道-信号量
linux
AndyHeee3 小时前
【瑞芯微rk3576刷ubuntu根文件系统容量不足问题解决】
linux·数据库·ubuntu
李昊哲小课3 小时前
Ubuntu 24.04 在线安装 Redis 8.x 完整教程
linux·redis·ubuntu
sao.hk3 小时前
ubuntu2404,vbox,全屏显示
linux·运维·服务器
危笑ioi3 小时前
linux配置nfs在ubuntu22.04
linux·运维·服务器
社会零时工3 小时前
【ROS2】海康相机ROS2设备服务节点开发
linux·c++·相机·ros2
东城绝神4 小时前
《Linux运维总结:Ubuntu 22.04配置chrony时间同步服务》
linux·运维·ubuntu·chrony
刘程佳4 小时前
Ubuntu 系统没有识别 Pixel 6 的 USB 设备权限
linux·运维·ubuntu