当前位置: 首页 > news >正文

Day 10:Shell正则表达式终极指南:从“抓狂“到“掌控“的奇幻之旅

目录

    • 一、正则流派之争:ERE vs PCRE
      • 1. 基础语法对比表
      • 2. 实战中的痛苦抉择
    • 二、零宽断言:正则中的"预言家"
      • 1. 四大预言术法
      • 2. 实战:提取引号内内容
    • 三、正则调试:从"盲猜"到"科学"
      • 1. 神器推荐:regex101
      • 2. Shell内置调试技巧
    • 四、性能优化:正则的"涡轮增压"
      • 1. 避免灾难性回溯
      • 2. 减少重定向的技巧
      • 3. 预编译正则(awk专属)
    • 五、终极实战:日志时间戳提取器
    • 课后挑战:构建正则测试框架

开篇:当你的正则表达式突然"叛变"

有没有经历过这些绝望时刻?

  • 花了2小时写的正则,匹配了不该匹配的内容
  • 在Stack Overflow复制的神奇正则,在你的Shell里居然失效了
  • 那个.*?在grep里怎么就不工作了?

今天,我要给你一本正则表达式生存手册,让你从"正则难民"变身"模式匹配大师"!

一、正则流派之争:ERE vs PCRE

1. 基础语法对比表

特性ERE (grep -E)PCRE (grep -P)
量词+, ?, {n,m}同上,支持懒惰模式+?
分组()() 和 (?😃
零宽断言不支持(?=), (?<=)
反向引用\1\1 和 \g{1}
字符类缩写[[:digit:]]\d

2. 实战中的痛苦抉择

# 提取带千分位的数字(PCRE才能用)
echo "1,234,567" | grep -Po '\d{1,3}(?:,\d{3})*'# ERE的替代方案(更复杂)
echo "1,234,567" | grep -Eo '[[:digit:]]{1,3}(,[[:digit:]]{3})*'

二、零宽断言:正则中的"预言家"

1. 四大预言术法

# 正向先行断言(?=) - 匹配后面跟着"元"的"人民"
echo "人民币 人民教师" | grep -Po '人民(?=元)'# 负向先行断言(?!) - 匹配后面不是"币"的"人民"
echo "人民币 人民教师" | grep -Po '人民(?!币)'# 正向后行断言(?<=) - 匹配前面是"中国"的"人民"
echo "中国人民" | grep -Po '(?<=中国)人民'# 负向后行断言(?<!) - 匹配前面不是"美国"的"人民"
echo "中国人民 美国人民" | grep -Po '(?<!美国)人民'

2. 实战:提取引号内内容

# 传统方式(贪婪匹配问题)
echo '"苹果", "香蕉"' | grep -Eo '".*"'  # 匹配整个"苹果", "香蕉"# 零宽断言方案(精确匹配)
echo '"苹果", "香蕉"' | grep -Po '(?<=")[^"]+(?=")'

三、正则调试:从"盲猜"到"科学"

1. 神器推荐:regex101

regex101.com 提供:

  • 实时高亮匹配结果
  • 详细模式解释
  • 多种语言兼容性测试

2. Shell内置调试技巧

# 分步测试复杂正则
pattern='([0-9]{4})-([0-9]{2})-([0-9]{2})'
echo "2023-08-01" | grep -E "$pattern" | awk '{print "年:", $1, "月:", $2, "日:", $3
}'

四、性能优化:正则的"涡轮增压"

1. 避免灾难性回溯

# 危险正则(可能卡死)
echo "aaaaaaaaaaaaaaaaaaaa!" | grep -E '(a+)+b'  # 永远找不到b# 优化方案
echo "aaaaaaaaaaaaaaaaaaaa!" | grep -E 'a+b'     # 快速失败

2. 减少重定向的技巧

# 低效写法(多次管道)
cat file | grep 'A' | grep 'B' | grep 'C'# 高效方案(单次处理)
grep -E 'A.*B.*C' file# 终极优化(使用awk)
awk '/A/ && /B/ && /C/' file

3. 预编译正则(awk专属)

awk 'BEGIN{pattern="^[0-9]+$"} $1 ~ pattern' file

五、终极实战:日志时间戳提取器

#!/bin/bash
# 支持多种时间格式:
# 2023-08-01 14:00:00
# 01/Aug/2023:14:00:00 +0800
# Aug  1 14:00:00extract_timestamps() {
grep -Po \
'(?:\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})|'\
'(?:\d{2}/\w{3}/\d{4}:\d{2}:\d{2}:\d{2} [+-]\d{4})|'\
'(?:\w{3} {1,2}\d{1,2} \d{2}:\d{2}:\d{2})' \
"$1" | while read -r ts; do# 统一转换为ISO格式date -d "$(echo "$ts" | sed 's#/# #g;s#:# #;s#\([A-Z][a-z]\{2\}\) \([0-9]\{2\}\)#\1 \2 #;s#+[0-9]\{4\}##;')" '+%Y-%m-%d %H:%M:%S'
done
}extract_timestamps /var/log/syslog | head -10

避坑指南:正则的"七宗罪"

  • 过度贪婪:.吃掉整个文件 → 改用.?(PCRE)或[^X]*
  • 编码陷阱:grep默认按字节处理 → 用LC_ALL=C grep处理二进制
  • 锚点遗漏:忘记用^$导致部分匹配
  • 平台差异:MacOS的grep与GNU版本不同 → 用ggrep(brew安装)

课后挑战:构建正则测试框架

需求:

  • ✅ 支持测试用例文件(输入+预期输出)
  • ✅ 显示失败用例的差异对比
  • ✅ 统计覆盖率(测试到的正则特性)

示例输出:

$ ./regex_tester.sh email_test.txt
[PASS] 测试用例1 (标准邮箱)
[FAIL] 测试用例2 (带+号的邮箱)
输入: user+tag@example.com
预期匹配: user+tag@example.com
实际匹配: user@example.com
http://www.lryc.cn/news/575951.html

相关文章:

  • 设计模式 | 桥接模式
  • LeetCode 349题解 | 两个数组的交集
  • SAP PP模块与MM模块作用详解
  • 航天VR赋能,无人机总测实验舱开启高效新篇​
  • Maven生命周期与阶段扩展深度解析
  • Linux系统(信号篇)信号的保存
  • Post-Training on PAI (1):一文览尽开源强化学习框架在PAI平台的应用
  • 信息抽取数据集全景分析:分类体系、技术演进与挑战_DEEPSEEK
  • CloudFormation 实现 GitHub Actions OIDC 与 AWS ECR 的安全集成(支持多组织配置)
  • 【Linux】ghb工具
  • 论文研读2-3:多GNSS双历元纯相位定位-定位精度分析
  • 【docker】docker run参数说明
  • 便利的隐形代价?智能设备正在“偷听”你的生活——物联网时代的隐私深度危机
  • 系统学习 Android 的 进程管理、内存管理、音频管理
  • Qt 与 Halcon 联合开发六:基于海康SDK设计完整的相机类【附源码】
  • 云计算与人工智能的融合:从弹性算力到智能云的IT新革命
  • 报道称CoreWeave洽谈收购Core Scientific,后者涨超30%
  • 内测开启!看海量化回测系统V2.0版本更新,基于miniQMT的回测系统问世!
  • Android 根据包名查看已安装应用的签名
  • 分布式session解决方案
  • 【Docker】解决:构建(docker build)或重新运行容器时,丢失apt-get update问题
  • 第三十一章 MCO——PA8从主频分频输出
  • 【数据挖掘】关联规则算法学习—Apriori
  • Gitee 持续集成与交付(CI/CD)篇
  • Solidity学习 - 断言失败
  • Java:链接mysql数据库报错:CommunicationsException: Communications link failure
  • MySQL Limit数量不满足时导致查询变慢
  • 深圳中青宝互动网络股份有限公司游戏运维工程师面试题(笔
  • 使用OpenCV进行3D重建:详细指南
  • OpenCV图像添加水印