「测试正则表达式」是什么意思?
测试正则表达式 (「regex test online」、「tester regex javascript」)就是把模式放到真实文本上运行,观察引擎到底返回什么:匹配到的字符串、它们的位置,以及捕获组的取值。一个「看起来正确」的模式在您的数据上跑过之前说明不了任何问题——教程里的正则和生产环境的正则,差别全在这里。
测试回答三个不同的问题。 是否匹配 :匹配项表格会逐行给出答案。 在哪里、匹配多长 :索引和长度能看出锚点是否放对了位置。 捕获了什么 :编号分组或命名分组能看出您打算提取的部分是否真的被捕获。
真正拉开差距的元字符
点号 . 可代替除换行符以外的任何字符——因此需要 s 标志,文本为多行时尤其需要。量词 *, + 和 ? 是 贪婪的 :在达到足够的重复次数后即停止。后缀 ? (*?, +?, {2,5}?)会反转这一行为,得到 惰性版本,几乎总是应该优先采用它——尤其当 .* 吞掉行尾时。
方括号用于定义字符类: [abc] 接受所列字符中的一个, [^abc] 除它们之外的任意字符, [a-z0-9] 一个区间。注意类开头处的取反—— [^...] 只对第一个位置生效,否则 ^ 会变回字面量。竖线 | 用于分隔备选项,且优先级最低: ^cat|dog$ 表示「整段文本等于 cat」或「整段文本等于 dog」,而不是「开头或结尾是 cat 或 dog」——这时就需要分组: ^(?:cat|dog)$.
分组、前瞻断言与后行断言
圆括号用于捕获。第 1 个分组可通过 $1 在替换侧引用,模式侧则用 \1 引用;命名分组则用 $<nom> 和 \k<nom> ——超过三个分组时可读性好得多。 (?:...) 只分组而不生成编号;只要您分组是为了结构,就应优先选择它。
断言(lookaround)只做检查而不消耗字符: (?=...) 要求后面的内容必须匹配, (?!...) 则禁止它出现, (?<=...) 和 (?<!...) 对前面的内容做同样的检查。这就是在密码中强制要求特殊字符、又不把它算进捕获的方式: ^(?=.*\d)(?=.*[A-Z]).{12,}$.
ReDoS:当正则表达式变成定时炸弹
所谓 ReDoS (Regular Expression Denial of Service) 源于 backtracking :面对几乎合规的输入时,类似 (a+)+$ 的模式会尝试所有切分 « a » 的方式才最终失败,而尝试次数呈指数增长。两条准则:在真实的数据量上测试模式——「性能」标签页会替您完成——绝不要在来自外部、没有大小限制的输入上运行无法审计的正则。在服务器上,卡住的正则会把整个 worker 冻住,直到超时为止。
JavaScript、PCRE、Python:同样的基础,些许差异
测试工具使用浏览器原生引擎,也就是 ECMAScript。基础语法——字符类、量词、分组、前瞻、标志 g i m s u y ——在 PCRE(PHP、Perl)、Python 的 re以及 Java 和 Go 中都是通用的。差异主要在 lookbehind(JavaScript 长期缺失,现已支持)、Unicode 属性,以及类似 (?i)这样的内联标志(PCRE 专有)。因此,把模式从一种语言搬到另一种语言只是细节活——无需重新发明。
推荐给
前端与后端开发者(表单校验、日志解析、数据迁移)、运维与 DevOps(配置过滤、WAF 规则)、测试与分析人员(列提取、格式校验)、编辑与数据分析师(文件清洗)、学生(理解元字符),以及任何需要 正则表达式测试工具 ——快速、完整、私密的人;配套工具还有 JSON 格式化工具、URL 编解码器、Base64 编解码器 以及 JWT 编解码器.