正规表示式测试
用你的文字测试正规表示式,即时标出每一个比对结果,并以白话拆解表示式中每个部分的作用。
在你的浏览器中运行
这个表达式的意思
读懂别人写的表示式
正规表示式的问题多半是「看不懂」:某人几年前把一段表示式贴进验证逻辑,之后就没有人说得出它到底 接受什么。下方的解说面板会把表示式拆成一个个构件并逐一说明,依序排列、按群组缩排,让表示式可以 用读的,而不是用猜的。
比对结果会在你输入的同时标示在测试文字上,最常见的两种错误因此一眼可见:比对范围比预期大,或是 在单字中间比对到、而不是整个单字。
旗标
| 旗标 | 作用 |
|---|---|
g | 找出全部,而不只是第一笔 |
i | 忽略大小写 |
m | ^ 与 $ 在每个换行处生效,而不只是整段文字的头尾 |
s | . 也会比对到换行 |
u | Unicode 模式,可使用 \u{…} 与 \p{…} |
m 是最常被需要、也最常被忘记设定的旗标。没有它,^ 只锚定整段文字的开头,逐行比对的表示式
会安静地只比对到一次就停住。
默认是贪婪的
.* 与 .+ 会先尽量吃掉最多的字元,再一个个吐回来,直到剩下的表示式能接上为止。对
<b>one</b> <b>two</b> 来说,<b>.*</b> 会比对到整串,而不是第一组标签。加上 ? 让量词变成
非贪婪,<b>.*?</b> 就会停在第一个结束标签。
一个字元的差别,就是「只抓到一个栏位」和「抓到整份文件」的差别。
灾难性回溯
巢状量词搭配互相重叠的选项,例如 (a+)+$,在比对不到的输入上会花费指数级的时间。几十个字元就
足以让引擎完全卡死——由于这个测试工具是在你自己的分页里执行,这样的表示式也会让这个页面冻结。
线上服务被这种表示式拖垮的案例并不罕见;常见的修法是让内层的选项互斥,让引擎没有可回溯的空间。
各家流派并不相同
这个页面使用浏览器本身的 JavaScript 引擎,所以你看到的结果就是 RegExp 的行为。其他流派相近但
不完全一样:
- 后行断言
(?<=…)在 JavaScript、Python 与 .NET 可用,但 Go 的 RE2 与多数 POSIX 工具不支援。 - 在 JavaScript 中
\d指的是 ASCII 数字(未加u时),Python 3 默认则会比对所有文字系统的数字。 - 具名群组在 JavaScript 与 .NET 是
(?<name>…),在 Python 是(?P<name>…)。
要在正式环境使用之前,请在实际会执行它的环境里再测一次。
你的数据只留在这里
表示式与文字都在你的浏览器中执行,不会传送到任何地方。当你拿来测试的样本是真实的日志或客户 数据时,这点特别重要。