如何使用正则表达式测试工具
- 输入不带两侧斜杠的模式,例如
\d{3}-\d{4}。 - 切换所需的标志(
g、i、m、s、u、y)。 - 粘贴测试文本。匹配结果会实时高亮显示,并列出每个捕获组。
- 也可以输入替换字符串,用
$1或$<name>引用分组,以预览结果。
该测试工具使用浏览器自带的 JavaScript 正则引擎。模式和测试数据都留在您的设备上,不会被上传或存储。
JavaScript 正则语法速览
不同语言的正则表达式风格有所不同。本工具采用 JavaScript(ECMAScript)风格,因此结果与浏览器和 Node.js 中 RegExp、String.prototype.match 和 replace 的行为一致。大部分语法可以沿用到 Python、PCRE 和 Java,但命名分组的写法和对后行断言的支持等细节各不相同。
标志
| 标志 | 名称 | 作用 |
|---|---|---|
g | global | 查找所有匹配,而不是在第一个匹配后停止。 |
i | ignoreCase | 不区分大小写匹配。 |
m | multiline | ^ 和 $ 匹配每一行的开头和结尾。 |
s | dotAll | . 也能匹配换行符。 |
u | unicode | 将模式视为 Unicode 码点;启用 \p{...} 属性转义。 |
y | sticky | 仅在 lastIndex 指定的位置匹配。 |
基本构件
- 字符类:
[abc],范围[a-z],取反[^0-9],简写\d(数字)、\w(单词字符)、\s(空白)及其反义\D、\W、\S。不带u标志时,\w和\d只涵盖 ASCII。 - 量词:
*(0 个或多个)、+(1 个或多个)、?(0 个或 1 个)、{n}、{n,}、{n,m}。在后面加?即变为懒惰模式:.*?。 - 分组:
(...)捕获,(?:...)分组但不捕获,(?<year>\d{4})创建命名分组,\1或\k<year>反向引用它。 - 锚点:
^、$和单词边界\b。 - 环视:
(?=...)正向先行断言,(?!...)负向先行断言,(?<=...)正向后行断言,(?<!...)负向后行断言。它们检查上下文而不消耗字符。
// Price amounts preceded by a dollar sign, without the sign
/(?<=\$)\d+(?:\.\d{2})?/g "Total: $42.50" → "42.50"
// Reformat dates with named groups
"2024-03-15".replace(/(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})/, "$<d>.$<m>.$<y>")
// "15.03.2024"
常用模式
| 用途 | 模式 | 局限 |
|---|---|---|
| 电子邮件(简易) | ^[^\s@]+@[^\s@]+\.[^\s@]+$ | 仅作合理性检查。完整的地址语法要复杂得多;请通过发送邮件来确认。 |
| IPv4 地址 | ^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$ | 拒绝大于 255 的段和前导零。不支持 IPv6。 |
| 日期(YYYY-MM-DD) | ^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$ | 接受 2023-02-31 这类不可能的日期。请用日期库来验证。 |
| URL(http/https) | ^https?:\/\/[^\s/$.?#][^\s]*$ | 宽松的检查。要真正解析,请使用 URL 构造函数。 |
专门针对 IP 地址,IP地址转换器可以解析并转换 IPv4 和 IPv6。
陷阱
灾难性回溯
嵌套或重叠的量词,会让像 JavaScript 这样的回溯引擎在匹配失败时尝试指数级数量的路径。几十个字符就可能让浏览器标签页卡死,在服务器上则可能引发拒绝服务攻击(ReDoS):
/^(a+)+$/.test("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!") // can hang
/^a+$/.test("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!") // instant
请避免 (a+)+、(a|a)* 或 (.*)* 这类模式,让各个分支互斥,并写得具体:在引号内,[^"]* 比 .* 更安全。
其他注意事项
- 带有
g标志的正则表达式会记住lastIndex,因此对同一个对象反复调用test()时,结果会在true和false之间交替。 - 用字符串构建模式时,反斜杠必须写两遍:
new RegExp("\\d+")。 - 忘记写
^和$,意味着验证器会接受任何仅仅包含匹配项的输入。
常见问题
为什么我的正则表达式在这里能用,在 Python 或 PHP 中却不行?
风格不同。Python 把命名分组写成 (?P<name>...),并且只支持定长的后行断言;PHP 的 PCRE 要求用定界符包裹模式。各语言中字符串字面量的转义规则也不一样。
贪婪量词和懒惰量词有什么区别?
贪婪量词(.*)尽可能多地匹配,然后再回退;懒惰量词(.*?)则尽可能少地匹配。对于 <b>x</b>,<.*> 匹配整个字符串,而 <.*?> 只匹配 <b>。
JavaScript 支持后行断言吗?
支持,自 ES2018 起,并且与许多引擎不同,它允许变长的后行断言。目前所有主流浏览器都支持。
如何匹配字面的点或括号?
用反斜杠转义:\.、\[、\(。在字符类内部,大多数字符都是字面含义,所以 [.] 同样能匹配一个点。
更新于