服务公告

服务公告 > 综合新闻 > 正则表达式:正则最佳实践

正则表达式:正则最佳实践

发布时间:2026-04-23 13:01

前言

搞过日志分析的人都知道,最烦的是写出一堆正则结果跑出来对不上号。本教程讲讲生产环境中真正能跑的正则最佳实践,从基础到高阶,从理论到踩坑。别整那些学院派花活,咱聊点实际能用的。

一、基础概念先捋清楚

正则这东西,入门简单想精通难。先把几个核心概念搞明白,后面的命令才能看懂。

1. 字符类与元字符

字符类是最基础的,[] 里面放要匹配的字符范围。

示例:匹配数字

[0-9]

等价于 \d,但生产环境里\d更简洁

示例:匹配字母

[a-zA-Z]

注意大小写敏感,这坑踩过的人不少

预期输出示例:

# 测试字符串 "abc123DEF456" # 正则 [0-9]+ 匹配到 "123" 和 "456" # 正则 [a-z]+ 匹配到 "abc" # 正则 [A-Z]+ 匹配到 "DEF"

2. 量词与贪婪/非贪婪

量词决定匹配多少,贪婪和非贪婪的区别能让你debug到怀疑人生。

贪婪模式(匹配最多)

# grep -E '".*"' 文件 # 会匹配从第一个"到最后一个"的所有内容

非贪婪模式(匹配最少)

# grep -E '".*?"' 文件 # 每个"..."单独匹配

预期输出示例:

字符串: "hello" world "test" 贪婪匹配".*": "hello" world "test" # 整个串 非贪婪匹配".*?": "hello" 和 "test" # 分开匹配

二、生产环境常用命令

步骤1:grep精确匹配日志

# CentOS/RHEL/Ubuntu通用 grep -E 'error|warn|critical' /var/log/messages

预期输出:

Jan 15 10:23:45 server01 kernel: error: connection timeout Jan 15 10:24:12 server01 nginx[1234]: warn: upstream failed Jan 15 10:25:01 server01 CRON[5678]: critical: backup failed

步骤2:sed批量替换(带备份)

# CentOS/RHEL sed -i.bak 's/old_pattern/new_pattern/g' /etc/app/config.conf # Ubuntu sudo sed -i 's/old_pattern/new_pattern/g' /etc/app/config.conf

警告:-i参数会直接修改文件,先备份!先备份!先备份!

预期输出:

# 执行后生成 config.conf.bak 备份文件 # 原文件已替换

步骤3:awk提取特定字段

# CentOS/RHEL/Ubuntu awk -F: '/nginx/ {print $1, $3}' /var/log/nginx/access.log

预期输出:

10.0.0.1 200 10.0.0.2 404 10.0.0.3 200 10.0.0.1 500

步骤4:find配合正则查找文件

# CentOS/RHEL/Ubuntu find /var/log -regex '.*/[0-9]{8}\.log$'

预期输出:

/var/log/nginx/access.20240115.log /var/log/nginx/access.20240116.log /var/log/nginx/error.20240115.log

步骤5:nginx日志统计实战

# 统计404请求的来源IP cat /var/log/nginx/access.log | grep " 404 " | awk '{print $1}' | sort | uniq -c | sort -rn | head -10

预期输出:

156 192.168.1.100 89 10.0.0.55 34 172.16.0.23 12 203.0.113.50

步骤6:nginx日志提取URL参数

# 提取请求路径和状态码(Ubuntu/CentOS通用) awk 'match($7, /\/api\/[^\?]+/) {print substr($7, RSTART, RLENGTH), $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn

预期输出:

2345 /api/users 1890 /api/orders 567 /api/products 123 /api/settings

三、常见问题FAQ

Q1:正则跑出来结果不对,怎么排查?

先把正则拆开逐步测试,别一口气写完。例如你想匹配IP,先单独测试匹配数字段,再组装。

# 单独测试各部分 echo "192.168.1.100" | grep -E '[0-9]+' # 验证数字匹配 echo "192.168.1.100" | grep -E '\.' # 验证点号转义 echo "192.168.1.100" | grep -E '^[0-9.]+$' # 完整IP正则

Q2:grep -E 和 grep -P 有什么区别?

-E 用的是扩展正则(ERE),-P 用的是Perl正则(PCRE)。生产环境优先用-E,兼容性更好。-P 功能强但部分系统不支持。

# CentOS/RHEL grep -E '\d+' /var/log/messages # 扩展正则 # Ubuntu grep -E '\d+' /var/log/syslog # 同样有效

Q3:为什么我的正则匹配不到空行?

空行匹配要用 ^$ 而不是 ^\s*$。如果还有问题,检查文件编码和行尾符。

# CentOS/RHEL grep -E '^$' /var/log/secure # 匹配空行 # Ubuntu grep -E '^$' /var/log/auth.log # 匹配空行 # 检查文件编码(通用) file /var/log/messages

Q4:sed替换想限制范围怎么写?

用行号限制替换范围,或者用地址模式。

# CentOS/RHEL/Ubuntu # 只替换第10-20行的内容 sed -i '10,20s/old/new/g' file.conf # 只替换包含关键词的行 sed -i '/database/s/old/new/g' file.conf # 多个模式 sed -i '/pattern1/,/pattern2/s/old/new/g' file.conf

四、总结

核心要点

  • 正则不是写得越短越好,能读懂才是关键
  • 生产环境先备份再操作,别相信自己的正则不会翻车
  • grep -E最通用,awk最灵活,sed适合批量替换
  • 遇到复杂匹配先拆解测试,不要一口气写完
  • 不同发行版路径不同,但正则语法基本通用

延伸阅读

  • man grep / man sed / man awk —— 官方文档永远最准
  • 《正则表达式必知必会》—— 工具书,案头备一本
  • regex101.com —— 在线调试正则,帮你验证语法
  • 《Linux命令行与shell脚本编程大全》—— 第15章正则部分讲得细

记住,正则这东西,得多练多踩坑。踩的坑多了,自然就熟了。