Shell中文本处理三剑客综合应用实例

文本处理三剑客简介

在Linux/Unix系统中,awk、grep和sed被称为"文本处理三剑客",它们各自有不同的专长:

  • grep:专门用于文本搜索,根据模式查找匹配的行
  • sed:流编辑器,用于文本的替换、删除、插入等编辑操作
  • awk:强大的文本分析工具,适用于字段处理和复杂的数据分析

这三个工具经常结合使用,通过管道符(|)连接,形成强大的文本处理流水线。

综合应用实例

1. 日志分析实例

假设我们有一个Web服务器访问日志文件access.log,内容如下:

192.168.1.10 - - [25/Jun/2023:12:34:56 +0000] "GET /index.html HTTP/1.1" 200 1234
192.168.1.15 - - [25/Jun/2023:12:35:00 +0000] "POST /login HTTP/1.1" 404 567
192.168.1.20 - - [25/Jun/2023:12:35:05 +0000] "GET /about.html HTTP/1.1" 200 789
192.168.1.10 - - [25/Jun/2023:12:36:10 +0000] "GET /contact.html HTTP/1.1" 500 234
192.168.1.25 - - [25/Jun/2023:12:36:15 +0000] "GET /products.html HTTP/1.1" 404 567

查找并统计404错误页面访问情况:

# 查找所有404错误的访问记录,提取IP地址并统计访问次数
grep "404" access.log | awk '{print $1}' | sort | uniq -c | sort -nr

这个命令的执行过程:

  1. grep "404" access.log - 筛选出包含"404"的行
  2. awk '{print $1}' - 提取每行的第一个字段(IP地址)
  3. sort - 对IP地址进行排序
  4. uniq -c - 统计每个IP出现的次数
  5. sort -nr - 按数字逆序排列,访问次数最多的在前面

查找错误请求并将状态码替换为描述性文字:

# 查找所有5xx错误,将状态码替换为描述性文字
grep "5[0-9][0-9]" access.log | sed 's/500/Internal Server Error/g' | awk '{print $1, $NF}'

这个命令的执行过程:

  1. grep "5[0-9][0-9]" access.log - 查找状态码为5xx的行
  2. sed 's/500/Internal Server Error/g' - 将500替换为Internal Server Error
  3. awk '{print $1, $NF}' - 打印IP地址和最后一个字段(通常是响应大小)

2. 系统管理实例

分析系统用户信息:

# 查找系统中普通用户(UID大于1000)并格式化输出
grep -v "^#" /etc/passwd | awk -F: '$3 > 1000 {print "用户:", $1, "UID:", $3, "家目录:", $6}' | sed 's/^/【普通用户】 /'

这个命令的执行过程:

  1. grep -v "^#" /etc/passwd - 排除注释行
  2. awk -F: '$3 > 1000 {print "用户:", $1, "UID:", $3, "家目录:", $6}' - 使用冒号分隔,筛选UID大于1000的用户并格式化输出
  3. sed 's/^/【普通用户】 /' - 在每行前面添加标识

分析磁盘使用情况:

# 获取磁盘使用率超过80%的分区并发出警告
df -h | grep -v "Filesystem" | awk '{if($5+0 > 80) print $1, $5}' | sed 's/$/ - 磁盘空间不足/'

这个命令的执行过程:

  1. df -h - 显示磁盘使用情况
  2. grep -v "Filesystem" - 排除标题行
  3. awk '{if($5+0 > 80) print $1, $5}' - 筛选使用率超过80%的分区
  4. sed 's/$/ - 磁盘空间不足/' - 在行尾添加警告信息

3. 数据处理实例

假设有以下CSV格式的数据文件data.csv:

姓名,年龄,城市,工资
张三,28,北京,8000
李四,32,上海,12000
王五,25,广州,7500
赵六,35,深圳,15000
钱七,29,杭州,9000

分析高薪员工信息:

# 查找工资超过10000的员工,按工资排序并格式化输出
grep -v "^姓名" data.csv | awk -F, '$4 > 10000 {print $4, $1, $3}' | sort -nr | sed 's/^/高薪员工: /'

这个命令的执行过程:

  1. grep -v "^姓名" data.csv - 排除标题行
  2. awk -F, '$4 > 10000 {print $4, $1, $3}' - 筛选工资超过10000的员工并打印相关信息
  3. sort -nr - 按工资数字逆序排列
  4. sed 's/^/高薪员工: /' - 添加标识前缀

统计各城市员工数量:

# 统计各城市员工数量并排序
grep -v "^姓名" data.csv | awk -F, '{print $3}' | sort | uniq -c | sort -nr | sed 's/^ */城市人数: /'

这个命令的执行过程:

  1. grep -v "^姓名" data.csv - 排除标题行
  2. awk -F, '{print $3}' - 提取城市列
  3. sort - 排序
  4. uniq -c - 统计各城市出现次数
  5. sort -nr - 按数量逆序排列
  6. sed 's/^ */城市人数: /' - 添加标识前缀

4. 配置文件处理实例

批量修改配置文件:

# 查找配置文件中的特定参数,修改其值并备份原文件
grep "^PORT=" config.ini | sed 's/PORT=.*/PORT=8080/' | tee config.ini.new && mv config.ini config.ini.bak && mv config.ini.new config.ini

这个命令的执行过程:

  1. grep "^PORT=" config.ini - 查找以PORT=开头的行
  2. sed 's/PORT=.*/PORT=8080/' - 将PORT的值修改为8080
  3. tee config.ini.new - 将结果保存到新文件并显示
  4. && mv config.ini config.ini.bak && mv config.ini.new config.ini - 备份原文件并使用新文件替换

5. 复杂文本处理实例

处理多行记录的日志文件:

# 处理多行错误日志,将相关联的行合并为单行
grep -B 2 -A 2 "ERROR" app.log | awk 'BEGIN{RS=""; FS="\n"} {print "错误记录:", $0}' | sed 's/\n/ | /g'

这个命令的执行过程:

  1. grep -B 2 -A 2 "ERROR" app.log - 查找包含ERROR的行及其前后各2行
  2. awk 'BEGIN{RS=""; FS="\n"} {print "错误记录:", $0}' - 将空行作为记录分隔符,将多行合并处理
  3. sed 's/\n/ | /g' - 将换行符替换为竖线分隔符

总结

通过以上实例可以看出,awk、grep和sed的组合使用能够处理各种复杂的文本处理任务:

  1. grep 负责精确查找和筛选需要处理的行
  2. sed 负责文本的编辑、替换和格式化
  3. awk 负责字段处理、条件判断和复杂的数据分析

在实际工作中,合理运用这三个工具的组合,可以大大提高文本处理的效率,完成原本需要编写复杂程序才能实现的功能。