前言
在 Linux 运维和开发中,正则表达式 是一个必不可少的工具。它能帮助我们快速处理日志、配置文件和大批量文本。本文将通过 grep
、sed
、awk
的结合使用,带你全面掌握常见的正则技巧,并给出实战案例。
1. 正则表达式基础
正则表达式(Regular Expression, regex)是一种 描述字符串模式的规则,常见用途包括:
日志筛选(查找错误或特定请求)
提取配置文件参数
文本批量替换
数据格式校验(邮箱、手机号等)
常见元字符
符号 | 含义 | 示例 |
---|---|---|
. |
任意单个字符 | a.b → acb , arb |
[] |
字符集合 | [0-9] 匹配数字 |
[^] |
非集合 | [^A-Z] 匹配非大写字母 |
^ |
行首 | ^ERROR 匹配以 ERROR 开头 |
$ |
行尾 | end$ 匹配以 end 结尾 |
* |
0 次或多次 | ba* → b , baaa |
+ |
1 次或多次 (ERE) | go+gle → google , gooogle |
? |
0 或 1 次 (ERE) | colou?r → color , colour |
{n} |
恰好 n 次 | [0-9]\{4\} → 4 位数字 |
{m,n} |
m 到 n 次 | [0-9]\{2,5\} → 2~5 位数字 |
` | ` | 或 |
() |
分组 | (ab)+ → ab 、abab |
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 练习
在
/etc/passwd
中查找所有以root
开头的行。从
ifconfig
或ip a
的输出中提取 IPv4 地址。在
access.log
中查找所有包含POST
的请求。
7.2 sed 练习
将
/etc/app.conf
文件中的端口8080
替换为9090
。删除
test.txt
文件中所有空行。删除
nginx.conf
文件中所有以#
开头的注释行。
7.3 awk 练习
打印
/etc/passwd
文件中的用户名和默认 shell(第 1 列和第 7 列)。统计
access.log
中每个 IP 出现的次数,并按从大到小排序。统计
access.log
中不同状态码的数量。
7.4 综合练习(小脚本)
编写一个脚本 log_analyzer.sh
,实现以下功能:
提取访问次数最多的前 5 个 IP
提取所有 500 错误的请求
统计 200、404、500 各类状态码的数量
8. 练习题与参考答案
8.1 grep 练习
题目
在
/etc/passwd
中查找所有以root
开头的行。从
ifconfig
或ip a
的输出中提取 IPv4 地址。在
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 练习
题目
将
/etc/app.conf
文件中的端口8080
替换为9090
。删除
test.txt
文件中所有空行。删除
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 练习
题目
打印
/etc/passwd
文件中的用户名和默认 shell(第 1 列和第 7 列)。统计
access.log
中每个 IP 出现的次数,并按从大到小排序。统计
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