Shell 编程 —— 正则表达式与文本处理实战

发布于:2025-09-02 ⋅ 阅读:(26) ⋅ 点赞:(0)

前言

1. 正则表达式基础

常见元字符

2. grep —— 文本查找

常用选项

示例

3. sed —— 文本替换与编辑

示例

4. awk —— 文本分析与报表

示例

5. 实战案例:Nginx 日志分析

5.1 访问最多的前 10 个 IP

5.2 查找 404 错误请求

5.3 统计状态码分布

5.4 最终脚本

6. 总结

7. 练习题

7.1 grep 练习

7.2 sed 练习

7.3 awk 练习

7.4 综合练习(小脚本)

8. 练习题与参考答案

8.1 grep 练习

8.2 sed 练习

8.3 awk 练习

8.4 综合练习(小脚本)

前言

在 Linux 运维和开发中,正则表达式 是一个必不可少的工具。它能帮助我们快速处理日志、配置文件和大批量文本。本文将通过 grepsedawk 的结合使用,带你全面掌握常见的正则技巧,并给出实战案例。


1. 正则表达式基础

正则表达式(Regular Expression, regex)是一种 描述字符串模式的规则,常见用途包括:

  • 日志筛选(查找错误或特定请求)

  • 提取配置文件参数

  • 文本批量替换

  • 数据格式校验(邮箱、手机号等)

常见元字符

符号 含义 示例
. 任意单个字符 a.bacb, arb
[] 字符集合 [0-9] 匹配数字
[^] 非集合 [^A-Z] 匹配非大写字母
^ 行首 ^ERROR 匹配以 ERROR 开头
$ 行尾 end$ 匹配以 end 结尾
* 0 次或多次 ba*b, baaa
+ 1 次或多次 (ERE) go+glegoogle, gooogle
? 0 或 1 次 (ERE) colou?rcolor, colour
{n} 恰好 n 次 [0-9]\{4\} → 4 位数字
{m,n} m 到 n 次 [0-9]\{2,5\} → 2~5 位数字
` `
() 分组 (ab)+ababab

2. grep —— 文本查找

grep 是最常用的正则工具,用于查找和过滤文本。

常用选项

  • -E:启用扩展正则

  • -i:忽略大小写

  • -n:显示行号

  • -v:反向匹配

  • -o:只输出匹配部分

示例

# 查找以 ERROR 开头的日志 
grep -n '^ERROR' app.log 
# 提取 IPv4 地址 
grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' ifconfig.out 
# 提取邮箱地址 
grep -oE '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-z]{2,}' users.txt

3. sed —— 文本替换与编辑

sed 是一个 流编辑器,适合对文件进行批量修改。

示例

# 把配置文件里的 8080 改成 9090 
sed -i 's/8080/9090/g' /etc/app.conf 
# 删除空行 
sed '/^$/d' test.txt 
# 提取邮箱所在行 
sed -n '/[a-zA-Z0-9._%+-]\+@[a-zA-Z0-9.-]\+\.[a-z]\{2,4\}/p' users.txt

4. awk —— 文本分析与报表

awk 擅长处理 结构化文本,比如日志和 CSV 文件。

示例

# 打印 /etc/passwd 的用户名 
awk -F: '{print $1}' /etc/passwd 
# 统计每个 IP 的访问次数 
awk '{print $1}' access.log | sort | uniq -c | sort -nr 
# 提取手机号(11 位数字) 
awk '/[0-9]{11}/ {print $0}' users.txt

5. 实战案例:Nginx 日志分析

假设有日志 /var/log/nginx/access.log

192.168.1.10 - - 
[01/Sep/2025:10:12:33 +0800] "GET /index.html HTTP/1.1" 
200 1024 192.168.1.11 - - 
[01/Sep/2025:10:12:35 +0800] "POST /login HTTP/1.1" 404 512 
192.168.1.12 - - 
[01/Sep/2025:10:12:36 +0800] "GET /admin HTTP/1.1" 403 256

5.1 访问最多的前 10 个 IP

awk '{print $1}'
access.log | sort | uniq -c | sort -nr | head -10

5.2 查找 404 错误请求

grep ' 404 ' access.log

5.3 统计状态码分布

awk '{print $9}' 
access.log | sort | uniq -c | sort -nr

5.4 最终脚本

#!/bin/bash 
logfile="/var/log/nginx/access.log" 
echo "====== 访问最多的前 10 个 IP ======" 
awk '{print $1}' 
$logfile | sort | uniq -c | sort -nr | head -10 
echo "====== 404 错误请求 ======" 
grep ' 404 ' 
$logfile 
echo "====== 状态码统计 ======" 
awk '{print $9}' 
$logfile | sort | uniq -c | sort -nr

6. 总结

  • grep:查找与过滤

  • sed:替换与编辑

  • awk:字段处理与统计

  • 三者结合,能完成从 日志搜索 → 文本替换 → 报表分析 的完整流程。 🚀

7. 练习题

下面给出一些常见的练习题,建议你在 Linux 环境下实际操作:

7.1 grep 练习

  1. /etc/passwd 中查找所有以 root 开头的行。

  2. ifconfigip a 的输出中提取 IPv4 地址。

  3. access.log 中查找所有包含 POST 的请求。

7.2 sed 练习

  1. /etc/app.conf 文件中的端口 8080 替换为 9090

  2. 删除 test.txt 文件中所有空行。

  3. 删除 nginx.conf 文件中所有以 # 开头的注释行。

7.3 awk 练习

  1. 打印 /etc/passwd 文件中的用户名和默认 shell(第 1 列和第 7 列)。

  2. 统计 access.log 中每个 IP 出现的次数,并按从大到小排序。

  3. 统计 access.log 中不同状态码的数量。

7.4 综合练习(小脚本)

编写一个脚本 log_analyzer.sh,实现以下功能:

  • 提取访问次数最多的前 5 个 IP

  • 提取所有 500 错误的请求

  • 统计 200、404、500 各类状态码的数量

8. 练习题与参考答案

8.1 grep 练习

题目

  1. /etc/passwd 中查找所有以 root 开头的行。

  2. ifconfigip a 的输出中提取 IPv4 地址。

  3. access.log 中查找所有包含 POST 的请求。

答案

# 1. 以 root 开头 
grep '^root' /etc/passwd 
# 2. 提取 IPv4 地址 
ifconfig | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' 
# 3. 查找 POST 请求 
grep 'POST' access.log

8.2 sed 练习

题目

  1. /etc/app.conf 文件中的端口 8080 替换为 9090

  2. 删除 test.txt 文件中所有空行。

  3. 删除 nginx.conf 文件中所有以 # 开头的注释行。

答案

# 1. 替换端口 
sed -i 's/8080/9090/g' /etc/app.conf 
# 2. 删除空行 
sed -i '/^$/d' test.txt 
# 3. 删除注释行 
sed -i '/^#/d' nginx.conf

8.3 awk 练习

题目

  1. 打印 /etc/passwd 文件中的用户名和默认 shell(第 1 列和第 7 列)。

  2. 统计 access.log 中每个 IP 出现的次数,并按从大到小排序。

  3. 统计 access.log 中不同状态码的数量。

答案

# 1. 用户名和默认 
shell awk -F: '{print $1, $7}' /etc/passwd 
# 2. 统计 IP 次数 
awk '{print $1}' access.log | sort | uniq -c | sort -nr 
# 3. 统计状态码数量 
awk '{print $9}' access.log | sort | uniq -c | sort -nr

8.4 综合练习(小脚本)

题目
编写一个脚本 log_analyzer.sh,实现以下功能:

  • 提取访问次数最多的前 5 个 IP

  • 提取所有 500 错误的请求

  • 统计 200、404、500 各类状态码的数量

参考脚本

#!/bin/bash 
logfile="access.log" 
echo "====== 访问最多的前 5 个 IP ======" 
awk '{print $1}' 
$logfile | sort | uniq -c | sort -nr | head -5 
echo "====== 500 错误请求 ======" 
grep ' 500 ' $logfile 
echo "====== 状态码统计 ======" 
awk '{print $9}' 
$logfile | grep -E '200|404|500' | sort | uniq -c | sort -nr

执行示例:

$ bash log_analyzer.sh
 ====== 访问最多的前 5 个 IP ====== 
150 192.168.1.10 120 192.168.1.11 ...
 ====== 500 错误请求 ====== 
192.168.1.12 - - 
[01/Sep/2025:10:12:36 +0800] "GET /admin HTTP/1.1" 500 512 
====== 状态码统计 ====== 
300 200 120 404 50 500