正则测试器:针对你自己的文本构建并调试模式
正则表达式(regex)是一门用于描述文本形状的微型语言。它让你不再问"这个确切的单词在这里吗?",而是能问"有没有一个看起来像这样的字符串?"正是这一点让它在代码编辑器、日志文件、表单输入和脚本中查找、校验、提取和替换文本时威力十足。也正是这一点让它容易出错,因为一个在你脑海里读起来没问题的模式,可能悄悄地匹配了太多、太少或什么都没匹配到。
这就是为什么交互式测试胜过靠猜。当你键入一个模式,看着匹配在真实的样本文本里逐一亮起,你就得到了即时反馈:你看到什么被捕获了、什么漏了过去,以及哪个捕获组抓住了哪一段。我们的正则测试器完全在你的浏览器中运行。你的模式和样本文本永远不会离开页面,所以你可以放心粘贴日志行、邮件或生产数据,而不向任何服务器发送任何东西。

值得了解的构件
大多数日常模式都由一小组零件组装而成。学会这些,你就能读懂在野外遇到的绝大多数正则。
字符类(character classes)描述一组允许的字符。[aeiou] 匹配任何单个元音,[0-9] 匹配一个数字,[a-zA-Z] 匹配一个字母。方括号内的脱字符(^)会对这个集合取反,所以 [^0-9] 表示"任何不是数字的字符"。简写能省去打字:\d 是一个数字,\w 是一个单词字符(字母、数字、下划线),\s 是空白,而点号 . 匹配几乎任何单个字符。
量词(quantifiers)说明前面那个零件可以重复多少次。* 表示零次或多次,+ 表示一次或多次,? 表示零次或一次(可选)。对于确切的次数,{3} 表示恰好三次,{2,4} 表示两到四次。所以 \d{4} 匹配一个四位的年份,而 colou?r 匹配两种拼写。
锚点(anchors)把模式钉在一个位置上,而不是一个字符上。^ 匹配文本的开头,$ 匹配结尾,\b 标记一个单词边界。模式 ^Error 只匹配以"Error"开头的行,这在扫描日志时正是你想要的。
分组(groups)用圆括号包住模式的一部分,既能对多个字符一次性应用一个量词,又能捕获匹配到的文本以便复用。在 (\d{4})-(\d{2})-(\d{2}) 里,每个组都捕获了一个你稍后能取出来的日期分量。用竖线表示的选择(alternation)作用像"或":cat|dog|fish 匹配这三个词中的任意一个。
你真正会用到的模式
少数几个反复出现的活儿覆盖了大部分实际工作。要捕获某个像邮件的东西,[\w.+-]+@[\w-]+\.[\w.-]+ 是一个务实的起点;按正式规范做完整的邮件校验是出了名的棘手,而一个宽松的模式通常是正确的选择——用于高亮候选项,而非拒绝用户。
对于数字,\d+ 抓取连续的数字,而 -?\d+(\.\d+)? 匹配可选的负号和小数。要去掉开头和结尾的空白,匹配 ^\s+|\s+$ 然后把它替换成空。要查找重复的单词,反向引用模式 \b(\w+)\s+\1\b 匹配一个单词后面跟着它自己,其中 \1 回指第一个捕获组。

标志改变匹配的行为
标志(flags)是修改整个模式的开关。全局标志(g)会找出每一处匹配,而不是在第一处停下,这正是你高亮所有出现位置时想要的。忽略大小写标志(i)让 error 同样匹配"Error"和"ERROR"。多行标志(m)改变 ^ 和 $,让它们在每一行的开头和结尾匹配,而不只是整段文本,这对逐行处理日志至关重要。其他有用的标志包括 s(dotall,让点号也能匹配换行)和 u(用于完整的 Unicode 处理)。
不同语言的风格略有差异
正则是一个方言家族,而非一个固定的标准。JavaScript、Python、PCRE(PHP)、Java、.NET、Go 和 Rust 在上面那些核心语法上是一致的,但它们在边缘处有所分歧:后行断言(lookbehind)的支持、命名组的语法((?<name>...) 对比 (?P<name>...))、Unicode 属性转义,以及存在哪些标志,全都各不相同。一个在某个引擎中能用的模式,到了另一个引擎可能需要一点微调,所以针对你实际发布所用的风格去测试是值得的。当你把一个模式调试妥当后,我们其他的开发者工具和文本工具能帮你完成清洗、编码和变换刚刚匹配到的数据这些周边工作。
常见问题
我的文本会被发送到服务器吗?
不会。正则测试器完全在你的浏览器中运行。你的模式和样本文本留在你的设备上,永远不会被上传,所以粘贴敏感数据是安全的。
这个工具使用哪种正则风格?
它使用你浏览器内置的 JavaScript 正则引擎。核心语法与你从大多数语言中熟悉的一致,不过一些高级特性与 PCRE、Python 或 .NET 略有不同。
贪婪匹配和懒惰匹配有什么区别?
默认情况下量词是贪婪的,会尽可能多地抓取文本。加一个问号会让它变懒惰,于是尽可能少地抓取。例如,点星这个模式是贪婪的,而点星问号是懒惰的。
我该如何匹配一个字面意义的特殊字符?
用反斜杠转义它。要匹配一个真正的点,写反斜杠点。其他元字符也是如此,例如圆括号、方括号、加号和问号。
为什么我的模式什么都没匹配到?
常见原因有:缺少全局标志、锚点把匹配钉在了错误的位置、有未转义的特殊字符,或者贪婪量词越过了你期望的边界。逐段测试来找出元凶。
我可以捕获匹配的某些部分吗?
可以。用圆括号包住模式的一段来创建一个捕获组。每个组都会被单独报告,这让你能从一个日期中提取出年、月、日等字段。
