免费的在线正则表达式测试工具:实时高亮匹配结果、列出每个捕获组、预览替换效果,并把正则逐段翻译成中文说明。内置手机号、身份证、邮箱、URL、车牌等中文场景常用正则,一键插入。全部在浏览器本地执行。
第一行写正则,下面贴测试文本,匹配结果实时出现:高亮区标出每一处匹配,匹配详情列出位置与捕获组,替换预览直接显示替换后的完整文本。不需要点任何「运行」按钮。
右上角的 g i m s u y 六个字母是标志位开关,鼠标悬停有中文说明。正则解释面板默认展开,把正则逐段翻译成中文——比如 \d{2,4} 会解释成「前面的内容重复 2 到 4 次」。看不懂别人的正则时,把正则贴进来读解释,比查语法表快。
「常用」一行内置了中文场景最常见的写法:手机号、身份证、邮箱、URL、日期、IP、车牌、统一社会信用代码、中文汉字、密码强度。点一下自动填入正则和一段示例文本,立刻看到效果。
量词默认是贪婪的:.* 会尽量多吃字符,吃到不能再吃才回退。<div>abc</div> 上跑 <div>.*</div> 会匹配整串,因为 .* 先把结尾的 </div> 也吞了,再一步步吐回来找最后能匹配的位置。
在量词后面加 ? 变成懒惰:<div>.*?</div> 只匹配到第一个 </div> 就停。另一条思路是排除字符类:<div>[^<]*</div> 用「不是 < 的字符」限定范围,既准确又不依赖回溯,性能也更好。
本工具的解释面板会把贪婪与懒惰的量词分别标注为「尽可能多」和「尽可能少」。
最常见的原因有三个。一是空格和不可见字符:肉眼看着一样,实际混了全角空格或不换行空格(\u00A0),用 \s 只能匹配部分,可以直接把可疑字符复制进字符类里。二是锚点用错:^ $ 在没有 m 标志时只匹配整个文本的开头和结尾,贴进来的文本带换行时它们的行为和你想的不一样。三是字符类里的范围写反了:[z-a] 会直接报错,浏览器的报错信息(Unterminated character class)会翻译成中文显示在正则输入框下面。
另一个高频坑是中文标点:文本里是全角逗号「,」,正则里写的却是半角「,」。这类问题高亮区一眼就能看出来——文本里没有变黄的地方就是没匹配上。
零宽断言(^ $ \b (?=...) (?!...) 等)匹配的是「位置」而不是「字符」,所以匹配结果的长度是 0。本工具对它们照常计数和高亮:比如 (?=a) 在 aaa 上会得到 3 处零宽匹配,高亮区看不到黄色但匹配详情里有 3 条记录。
实际用途举两个例子:\b 是单词边界,用来把 abc 从 xabc 里区分出来;(?=\d{4}) 是先行断言,「后面必须跟 4 位数字」,常用于在长串里定位特定格式的起点而不消耗字符。
圆括号 () 把一部分正则变成捕获组,匹配到的内容按左括号顺序编号,$1、$2 在替换串里引用;(?:...) 是非捕获组,只分组不编号;(?<名字>...) 是命名捕获组,替换串里用 $<名字> 引用。
反向引用 \1 表示「这里的内容要和第 1 组匹配到的完全一样」,典型用法是找重复单词:\b(\w+) \1\b 能把 double double 找出来。注意反向引用匹配的是那一组当时匹配到的内容,不是那段正则本身。
匹配详情里每个捕获组单独列出,可选组没参与匹配时会明确标注「未参与」,而不是显示成空串。
这几乎总是「灾难性回溯」造成的。正则引擎在匹配失败时会退回去尝试其他路径,嵌套量词(形如 (a+)+、(\d*)* 的写法)会让路径数指数级增长。本工具实测:(a+)+$ 对 20 个 a 加一个 b 就要跑将近 0.8 秒,30 个 a 要跑几分钟。原因不是文本长,是组合数爆炸。
改法有三个方向:把嵌套量词展开写((a+)+ 改成 a+);用否定字符类限制范围([^a] 比 . 便宜得多);在开头加锚点 ^ 让引擎尽早放弃。如果确认自己的正则就是慢但能跑完,超时提示下有「仍然要算」按钮,会放宽到 5 秒再算一次。
匹配在后台线程执行,超时后直接终止线程重建,所以无论正则多离谱,页面都不会卡死——这是本工具和很多同类工具的硬差别。
本工具按 JavaScript 的 RegExp 语义执行,测试通过不代表其他语言也能用,主要差异有三处:命名捕获组在 Python 里写作 (?P<名字>...) 而不是 (?<名字>...);Unicode 属性 \p{...} 在 JavaScript 里必须开 u 标志,PCRE 不需要;后行断言 (?<=...) 在旧版 JavaScript 引擎里不支持。
反向引用、先行断言、懒惰量词这些核心语义各家基本一致,测出来的行为可以直接迁移;但凡是用了语言特有扩展的正则,请以目标语言的环境为准。
多半是「灾难性回溯」:嵌套量词(如 (a+)+)遇到不匹配的文本时,正则引擎会尝试指数级的组合路径。本工具实测 (a+)+$ 对 20 个 a 加一个 b 就要跑约 0.8 秒,30 个 a 要几分钟。改法:把嵌套量词展开写、用否定字符类缩小范围、在开头加锚点。如果确信能跑完,可以点「仍然要算(可能卡住几秒)」放宽到 5 秒。匹配在线程池里跑,超时会直接终止线程,页面不会卡死。
核心语义(字符类、量词、贪婪懒惰、先行断言、反向引用)各家基本一致,可以直接迁移。但有几处已知差异:命名捕获组 Python 写 (?P<name>...),JavaScript 写 (?<name>...);\p{...} 在 JavaScript 里必须配合 u 标志;Python 的 re 模块默认不做任何 Unicode 属性判断。本页面按 JavaScript 的 RegExp 语义执行,用于其他语言前请以目标环境为准。
不会。匹配计算全部在浏览器本地线程里完成,文本和正则都不经过服务器。这一点可以直接验证:断网后本页面依然能正常工作(首次加载后)。
高亮是把每个匹配渲染成独立的标记元素,10 万个标记会让浏览器渲染明显卡顿,超过 1 万处时人也读不过来。达到上限后工具会明确提示「只显示了前 10000 处」,匹配详情按同样的上限截断。要统计总数而不是看位置的话,建议缩小文本范围分批测。
最常用的是 [\u4e00-\u9fa5]+,覆盖基本区 20902 个汉字,日常文本足够。它有两个已知盲区:扩展区汉字(如 𠀀,码点超过 U+FFFF)和兼容区汉字不在这个区间里。要覆盖扩展区需要开 u 标志后用 \p{Script=Han},这是按 Unicode 脚本属性匹配,更准确但把日文汉字等也一并算进来。本工具的「中文汉字」预设用的是前者,附注里写明了取舍。
$1 引用第 1 个捕获组匹配到的内容,$2 是第 2 个,以此类推;$& 是整个匹配;$$ 是字面量 $ 字符本身;$<名字> 引用命名捕获组。如果正则里没有捕获组而你写了 $1,它会原样输出 $1 这三个字符——这是规范行为,不是 bug。本工具的替换预览直接用浏览器原生替换逻辑,所有这些符号的行为与你在代码里写 text.replace(...) 完全一致。