跳到内容
GitHub 仓库 论坛 RSS 新闻提要

注意:Crystal 正在升级其正则表达式引擎

Beta Ziliani

Crystal 自诞生以来一直使用 PCRE 库来处理正则表达式。该库有两个主要版本,Crystal 目前使用的是第一个版本 (PCRE)。但是,该版本已达到其生命周期结束。因此,在下一个版本 (1.8) 中,我们计划迁移到其继任者 PCRE2。

PCRE 与 PCRE2

这两个库版本 PCRE 和 PCRE2 在很大程度上彼此兼容。存在一些细微差别,可能会导致破坏性变更。但我们预计不会遇到太多问题。最值得注意的是,PCRE2 在某些极端情况下比 PCRE 更严格。这意味着 PCRE 可能接受了一些无效的正则表达式,但 PCRE2 不会接受它们。

不幸的是,没有指南 来帮助移植。变更最详细的列表是 Stackoverflow 上的这个帖子

从好的方面来说,PCRE2 扩展了对有趣功能的支持。您可以在这个 维基百科文章项目文档 中了解更多关于其功能的信息。

正则表达式字面量验证

为了理解以下路线图,重要的是要明确编译器和标准库在正则表达式方面的一个现有区别。当您编写类似 /(a|b)*/.match "abba" 的代码时,编译器 会检查正则表达式字面量 (/(a|b)/) 的有效性。无效的表达式会导致语法错误。然后,在执行程序时,正则表达式库的标准库 绑定将执行匹配的实际执行操作。

这种差异会产生一个后果:您可以使用一个库检查正则表达式字面量,然后使用另一个库执行它们。

在最后一个版本 (1.7) 中,我们已经添加了在标准库中通过 编译器标志 选择使用 PCRE2 的可能性。这意味着如果您在系统中安装了 1.7 和 PCRE2,您可以使用 -Duse_pcre2 编译您的程序或分片,然后执行它以查看是否有任何正则表达式在运行时失败。如果正则表达式失败,则必须将其重写以符合 PCRE2。

在即将发布的版本中,PCRE2 将默认情况下由编译器和标准库使用。您仍然可以通过编译器标志 -Duse_pcre 在标准库中使用 PCRE,以防某些东西出现故障。但编译器将始终使用 PCRE2 来验证正则表达式字面量。这对一致性很重要,因为它直接影响 Crystal 的语法。

如果您需要继续使用旧的 PCRE,而编译器由于 PCRE2 中的限制而将字面量视为无效,您可以将字面量转换为 Regex.new 调用,该调用将表达式作为字符串字面量接收。出于性能原因,建议缓存 Regex 实例(例如在常量中)。

将您的项目迁移到 PCRE2

我们离 1.8 还有一个月以上的时间,这给了我们时间将更改引入 nightly 版本,并让社区测试其分片和项目以发现不兼容性。

因此,为了做好准备,我们建议您:

  1. 如果您使用的是 1.7,请使用编译器标志 -Duse_pcre2 检查您的项目的运行状况。

  2. 如果您使用的是 nightly 版本,它们已经使用 PCRE2。要获得旧的行为,您需要添加 -Duse_pcre(记住,这只影响运行时 行为,而不是语法或正则表达式字面量)。

  3. 修复所有导致问题的正则表达式(如果有)。

  4. 如果您在步骤 2 中添加了 -Duse_pcre,请将其删除:1.9 之后将不再保证对 PCRE 的支持。

如果您的项目由于此更改而出现故障,请告知我们。我们将收集信息并分享针对常见问题的修复方案。

⚠️ 包维护者 ⚠️

请最晚在 1.8 中切换到 PCRE2。