很多人用awk只是简单的awk ‘{print $1}‘打印某一列,其实awk是一个功能强大的文本处理工具,掌握这些高级用法后,你会发现很多复杂的数据处理任务都能一行命令搞定。感兴趣的同学可以Mark一下。
- 统计分析 - 一键计算数据指标 日志分析、数据统计不用写复杂脚本,awk内置了丰富的统计功能:
# 统计文件行数、字数、字符数
awk 'END{print NR, NF, length}' file.txt
# 计算某列的总和、平均值
awk '{sum+=$3} END{print "总和:", sum, "平均值:", sum/NR}' data.txt
# 找出某列的最大值、最小值
awk 'NR==1{max=min=$2} {if($2>max) max=$2; if($2<min) min=$2} END{print "最大值:", max, "最小值:", min}' data.txt
【场景举例】分析Web服务器访问日志,统计总请求数、平均响应时间、最大响应时间。
- 条件过滤 - 灵活筛选数据 比grep更强大的条件过滤,支持数值比较、字符串匹配、正则表达式:
# 筛选某列大于指定值的行
awk '$3 > 100' data.txt
# 多条件组合过滤
awk '$2 == "ERROR" && $4 > 500' log.txt
# 正则表达式匹配
awk '$1 ~ /^192\.168\./' access.log
# 反向匹配(不包含)
awk '$0 !~ /debug|info/' log.txt
- 字段处理 - 动态操作列数据 不只是打印列,还能动态计算、转换、重组数据:
# 动态计算新字段
awk '{print $1, $2, $3*$4}' data.txt
# 字符串拼接和格式化
awk '{printf "用户: %s, 得分: %.2f分\n", $1, $2}' score.txt
# 字段重排序
awk '{print $3, $1, $2}' data.txt
# 字段数量变化时的处理
awk '{for(i=2; i<=NF; i++) sum+=$i; print $1, sum; sum=0}' data.txt
- 分组统计 - 按类别汇总数据 像SQL的GROUP BY一样,按某个字段分组统计:
# 按第一列分组,统计每组的数量
awk '{count[$1]++} END{for(key in count) print key, count[key]}' data.txt
# 按多个字段分组
awk '{key=$1"_"$2; sum[key]+=$3} END{for(k in sum) print k, sum[k]}' data.txt
# 分组求平均值
awk '{sum[$1]+=$2; count[$1]++} END{for(k in sum) print k, sum[k]/count[k]}' data.txt
【场景举例】分析销售数据,按地区统计总销量、平均客单价。
- 数据转换 - 格式化输出 将原始数据转换成需要的格式,生成报表或其他格式:
# 转换成JSON格式
awk '{printf "{\"name\":\"%s\", \"score\":%d}\n", $1, $2}' data.txt
# 生成HTML表格
awk 'BEGIN{print "<table>"} {print "<tr><td>"$1"</td><td>"$2"</td></tr>"} END{print "</table>"}' data.txt
# 转换时间格式
awk '{gsub(/-/, "/", $1); print $1, $2}' date.txt
# 数值格式化(添加千分位逗号)
awk '{printf "%'"'"'d\n", $1}' numbers.txt
- 多文件处理 - 关联和对比数据 处理多个文件,实现数据关联、对比、合并:
# 关联两个文件(类似SQL JOIN)
awk 'NR==FNR{a[$1]=$2; next} {print $0, a[$1]}' file1.txt file2.txt
# 找出两个文件的差异
awk 'NR==FNR{a[$0]=1; next} !($0 in a)' file1.txt file2.txt
# 合并多个文件并添加来源标识
awk '{print FILENAME, $0}' *.txt
- 时间日期处理 - 日志分析利器 处理带时间戳的日志文件,进行时间范围过滤和统计:
# 过滤指定时间范围的日志
awk '$1 >= "2024-01-01" && $1 <= "2024-01-31"' access.log
# 按小时统计访问量
awk '{hour=substr($2, 1, 2); count[hour]++} END{for(h in count) print h":00", count[h]}' access.log
# 计算时间间隔
awk 'NR==1{start=$1} END{print "处理时长:", $1-start, "秒"}' time.log
- 高级模式匹配 - 灵活处理复杂文本 处理结构化文本、配置文件、多行记录:
# 处理多行记录(空行分隔)
awk 'BEGIN{RS=""} {print "记录", NR":", $0}' records.txt
# 自定义字段分隔符
awk -F'[:,]' '{print $2, $4}' config.txt
# 范围模式匹配
awk '/START/,/END/ {print}' log.txt
# 跳过注释和空行
awk '!/^#/ && !/^$/ {print}' config.txt
- 数据验证 - 检查数据质量 快速检查数据完整性、格式正确性:
# 检查必填字段
awk 'NF < 3 {print "第"NR"行缺少字段:", $0}' data.txt
# 验证数据格式
awk '$2 !~ /^[0-9]+$/ {print "第"NR"行数据格式错误:", $0}' numbers.txt
# 检查重复数据
awk '{if(seen[$1]++) print "重复记录:", $0}' data.txt
# 数据范围验证
awk '$3 < 0 || $3 > 100 {print "异常数据:", $0}' scores.txt
- 一键生成报表 - 复杂统计输出 组合多种功能,生成专业的数据报表:
# 生成销售报表
awk '
BEGIN {
print "=== 销售数据分析报表 ==="
print "日期\t\t销售额\t\t同比"
print "------------------------"
}
{
date=$1; amount=$2
total += amount
data[date] = amount
}
END {
for(d in data) {
printf "%s\t\t%.2f\t\t%.1f%%\n", d, data[d], (data[d]/total)*100
}
print "------------------------"
printf "总计:\t\t%.2f\n", total
printf "平均:\t\t%.2f\n", total/NR
}
' sales.txt
结语 #
awk的强大之处在于它能用简洁的语法完成复杂的数据处理任务。掌握这些高级用法后,你会发现很多原本需要写脚本才能完成的工作,一行awk命令就能搞定。下次处理数据时,不妨试试这些技巧,说不定能大大提升你的工作效率!