AWK 是一种强大的文本处理工具,广泛应用于日志分析、数据清洗和文本格式化等任务。本文将通过丰富的实战案例,带你从基础到高级逐步掌握 AWK 的应用技巧,提升你的文本处理能力。
1. AWK 基础用法
1.1 打印第一行的第一个字段
最基本的 AWK 用法是打印某一行的特定字段。例如,打印第一行的第一个字段:
awk 'NR==1 {print $1}' file.txt
解释:
NR==1:表示只处理第一行。{print $1}:打印第一列的数据。
1.2 提取文本信息
AWK 非常适合从文本中提取特定字段。例如,获取系统中所有运行的进程 ID:
ps | awk '{print $1}'
从 /etc/passwd 中提取用户名:
awk -F ":" '{print $1}' /etc/passwd
1.3 条件筛选
AWK 也支持根据条件筛选数据。例如,筛选 /etc/shells 文件中行长度大于 7 的文本:
awk 'length($0) > 7' /etc/shells
筛选出内容等于 /bin/bash 的行:
awk '{if ($0=="/bin/bash") print $0}' /etc/shells
1.4 基本计算
AWK 支持基本的数学运算和控制流,例如输出 1 到 10 的平方:
awk 'BEGIN{for(i=1;i<=10;i++) print "数字",i,"的平方为",i*i}'
2. 筛选和汇总数据
假设有一个 data.txt 文件,内容如下:
100 John
200 Jane
300 Bob
你可以使用 AWK 筛选出金额大于 150 的记录,并计算总金额:
awk '$1 > 150 { print $0; total += $1 } END { print "Total: " total }' data.txt
解释:
- 模式:
$1 > 150匹配第一个字段(即金额)大于 150 的记录。 - 动作:
print $0:打印整行。total += $1:将金额累加到变量total中。
- END 块:在处理完所有记录后,输出总金额。
输出:
200 Jane
300 Bob
Total: 500
3. AWK 高级用法
3.1 管道操作
AWK 常常与其他命令结合使用来处理复杂的任务。例如,启动 Docker 容器:
docker ps -a | awk '{print $1}' | tail -n +2 | xargs docker start
停止 Docker 容器:
docker ps -a | awk '{print $1}' | tail -n +2 | xargs docker stop
3.2 字符匹配
使用正则表达式在 AWK 中进行字段匹配。例如,筛选字段末尾不包含 test 的 Docker 容器:
docker ps | awk '!match($NF,/^test/) {print NR,$NF}'
3.3 字段统计
打印 /etc/shells 文件的最后一个字段并去重:
awk -F "/" '/^\// {print $NF}' /etc/shells | sort -u
/^\//是一个正则表达式,用于匹配以斜杠/开头的行。
3.4 脚本特性:修改输出字段分隔符
使用 BEGIN 和 END 块来设置输出字段分隔符。例如:
awk 'BEGIN {OFS=":"} {print $1, $2} END {print "Done"}'
BEGIN {OFS=":"}设置输出字段分隔符为冒号:。END {print "Done"}在输出所有数据后打印"Done"。
4. AWK 实战案例:去重时间字段
假设有如下文件 file:
2012-02|hais|3
2012-02|Spim|3
2012-02|Spis|2
2012-02|Uart|4
2012-03|Hais|11
2012-03|Mux|6
2012-03|Scc|7
2012-04|Hais|2
2012-04|Top|1
4.1 需求:时间重复的项只保留第一个时间
你可以使用以下 AWK 命令来实现此需求:
cat file | awk 'BEGIN{FS="|";OFS="|"} a==$2 {print "||"$3,$4"|"; next} {a=$2} 1'
解释:
FS="|"设置输入字段分隔符为管道符|。OFS="|"设置输出字段分隔符为管道符|。a==$2检查当前行的时间字段是否与前一行相同,若相同,则输出||来表示去重。next跳过重复的行,继续处理下一行。
5. 高级技巧
5.1 嵌套条件
通过复杂的条件筛选数据。例如,从日志中筛选出错误条目:
awk '{if ($3=="ERROR" && $5>10) print $0}' server.log
这会输出日志中第 3 字段为 ERROR 且第 5 字段大于 10 的所有行。
5.2 自定义函数
AWK 支持定义函数来实现复杂的计算。例如,计算 Fibonacci 数列:
awk 'function fib(n) {if (n<=2) return 1; else return fib(n-1)+fib(n-2)} BEGIN {for(i=1;i<=10;i++) print fib(i)}'
5.3 多文件处理
AWK 可以同时处理多个文件并根据字段进行匹配。例如,合并两个文件,并根据第一个字段进行匹配:
awk 'NR==FNR{a[$1]=$2; next} $1 in a {print $1, $2, a[$1]}' file1 file2
- 这里
NR==FNR表示在处理第一个文件时,保存文件的字段值到数组a中。 - 然后,在处理第二个文件时,输出匹配的字段。
6. 性能优化
6.1 减少重复计算
避免在循环中进行重复计算,可以提高性能。例如,计算总和:
awk '{sum+=$2} END {print "总和:", sum}' data.txt
6.2 逐行处理大文件
使用 getline 逐行处理大文件,避免一次性加载大文件占用过多内存:
awk '{while (getline < "file.txt") print $0}'
这样,AWK 只会在需要时从文件中读取数据,减少内存的使用。
总结
通过本文的案例,你已经学习了 AWK 的基础操作、高级技巧和实战应用。无论是简单的字段提取,还是复杂的数据处理,AWK 都能为你提供强大且灵活的解决方案。掌握这些技巧,你可以大大提升在处理文本数据、日志分析等任务中的效率。
原文 https://blog.csdn.net/2301_79518550/article/details/144570977