// Linux · 2024-12-18

AWK 从入门到精通:丰富实战案例

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