Sequence properties in Unicode property escapes ?
中文标题:Unicode 属性转义中的字符串序列属性
- 阶段: 未分阶段
- 状态: 已撤回
- ECMAScript 版本: —
- 同步时间: 2026年8月26日
- English original · 官方仓库
该提案解决了 Unicode 属性转义仅支持扩展为码点集的属性,而不支持多字符字符串的限制。它建议重用现有的 \\p{.} 语法来支持几个 Unicode 序列属性,如 RGI_Emoji_ZWJ_Sequence,从而能够匹配 emoji 序列。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
ECMAScript 提案:在 Unicode 属性转义中支持字符串属性(又名“序列属性”)
状态
该提案处于 TC39 流程 的第 2 阶段。
注意,RegExp v 标志提案 涵盖了本提案——并增加了字符类中的集合表示法和字符串字面量。
术语
本提案最初使用了“序列属性”这一术语,但这用词不当。字符序列是一个字符串,而字符串属性是指其值(值域)为字符串的属性,正如二元属性是指其值为二元的真/假(即属性是否适用)。
Unicode 此后已对此进行了正式化,使用“码点属性”和“字符串属性”来指属性的定义域。参见 https://www.unicode.org/reports/tr18/#domain_of_properties。
此外,我们主要在“字符”和“码点”之间互换使用。更正式地说,“字符”指的是已分配的码点,但属性对所有码点都有值。(大多数属性将所有未分配的码点映射到一个默认值。)
动机
Unicode 标准为每个字符/码点分配了各种属性和属性值。例如,Unicode 字符数据库提供了数据,用于精确确定 Script 属性值为 Greek 的字符集合。
Unicode 属性转义 使 JavaScript 开发者能够在 ECMAScript 正则表达式中原生访问这些 Unicode 字符属性。
在 Unicode 属性转义中当前支持的 Unicode 属性和值有一个共同点:它们都扩展为一组码点。此类转义可以转译为一个字符类,其中包含它们单独匹配的码点。例如,\p{ASCII_Hex_Digit} 等价于 [0-9A-Fa-f]:它每次只匹配一个 Unicode 字符/码点。
然而,Unicode 标准还定义了若干字符串属性。在正则表达式中,此类属性会转化为一组备选项。为了说明这一点,设想一个 Unicode 属性适用于字符串 'a'、'b'、'c'、'W'、'xy' 和 'xyz'。该属性转化为以下任一正则表达式模式(使用 alternation):xyz|xy|a|b|c|W 或 xyz|xy|[a-cW]。(最长的字符串在前,这样如 'xy' 这样的前缀不会隐藏如 'xyz' 这样的更长字符串。)请注意,与现有 Unicode 属性转义不同,此模式可以匹配多字符字符串。
手写的这些属性的正则表达式会遭受与 Unicode 属性转义所解决的相同问题:它们难以手动编写或维护,往往体积较大,且可读性差。
提议的解决方案
我们提议在现有的 Unicode 属性转义语法中增加若干_字符串属性_。
有了此功能,上述正则表达式可以写成:
我们提议支持以下在 UTS18 和 UTS51 中定义的 Unicode 序列属性:
Basic_EmojiEmoji_Keycap_SequenceRGI_Emoji_Modifier_SequenceRGI_Emoji_Flag_SequenceRGI_Emoji_Tag_SequenceRGI_Emoji_ZWJ_SequenceRGI_Emoji
这些序列属性中的每一个都扩展为一个有限的、定义明确的字符串集合。(Basic_Emoji 也适用于许多单个字符。)
随着时间推移,我们可以选择支持额外的字符串属性,遵循上游 Unicode 标准。
高级 API
对这个新功能重用现有的 Unicode 属性转义语法似乎是合适的:
其中 PropertyName 可以是上面列出的字符串属性之一。
不支持此类属性的补集:如果 PropertyName 是字符串属性,则 \P{PropertyName} 和 [^…\p{PropertyName}…] 都会抛出早期的 SyntaxError 异常。
我们思考过此类补集的可能定义,但认为它们通常没有用处。
可以通过负向前瞻来支持“不是字符串属性”的某些用例:/(?!\p{RGI_Emoji_Flag_Sequence})\p{Symbol}/u。
注意: 在字符类中使用字符串属性等价于所有字符串和字符的交替,其中元素的顺序无关紧要(例如,按最长字符串优先列出)。(这可以通过保留单字符的字符类来优化,如动机部分所示。)
常见问题
向后兼容性如何?
对不支持的 Unicode 属性的 Unicode 属性转义会抛出早期的 SyntaxError。因此,只要我们重用现有语法,就可以以向后兼容的方式添加对新属性的支持。
字符类中的字符串属性
目前,每个属性转义和字符类都扩展为一组码点,等价于单个字符的交替。使用本提案后,属性转义和字符类扩展为一组字符串,等价于字符串的交替。在大多数情况下,这些字符串中的大部分或全部仍然是单字符字符串。
例如:[\p{Emoji_Keycap_Sequence}\p{Symbol}] = #⃣|*⃣|0⃣|1⃣|…|9⃣|[\$+<->\^…℻⅀-⅄⅊-⅍…]
为什么要重用 \p{…} 而不是引入新语法?
引入新语法会给 JavaScript 开发者带来成本。在这种情况下,我们认为为此功能添加新语法的成本超过了收益。
新语法可以用于字符串属性。但是,这种新语法也应该允许码点属性,这样,当 Unicode 属性在后续 Unicode 版本中不再适用于多字符字符串时,现有的正则表达式仍然有效。
因此,开发者应该知道哪些属性适用于字符串,或曾经适用过,但对他们来说,简单地切换所有属性使用新语法会更容易。
正则表达式可以通过解析器使用关于哪些属性适用于字符串 vs. 仅单个字符的信息来验证,而无需新的转义。
心理模型是:\p{…} 指的是 Unicode 属性。它匹配属性定义域中其值为真的元素。本提案不改变这一点。假设选择使用字符串属性的开发者知道会发生什么,这是合理的。
示例
匹配 emoji 序列
通过本提案,RGI(通用交换推荐)emoji 集合(字符_和_序列!)可以在 JavaScript 中轻松表示为一个 RegExp 模式:
不使用属性转义的等价正则表达式 大小约为 7 kB。使用属性转义但不支持字符串属性,大小约为 4.5 kB。上述带序列属性的正则表达式仅占 16 字节。
匹配 hashtags
许多应用程序(如 Twitter)使用允许 emoji 字符的扩展 hashtag。Unicode® 标准附录 #31 定义了 扩展 Hashtag 标识符语法 (UAX31-R8) 为匹配:
上述模式匹配 emoji,但也匹配语法上无效的 emoji 以及不推荐用于通用交换的 emoji。然而,有了提议的功能,匹配仅包含有效和推荐 emoji 的 hashtag 变得可行:
不使用属性转义的等价正则表达式 大小约为 12 kB。使用属性转义但不支持字符串属性,大小约为 3 kB。上述带序列属性的正则表达式仅占 62 字节。
相关的 UTC 提案
- L2/18-337 扩大 Unicode 所称“属性”的范围
- L2/19-168 在正则表达式中支持字符串属性(带演讲者备注的幻灯片)
- Unicode® 技术标准 #18 工作草案 #20
- Mark Davis 的演示
- L2/20-056: UTS #18 正则表达式特设:字符串属性的
\pvs.\m
TC39 会议记录
- 2018 年 5 月
- 2018 年 9 月
- 2019 年 1 月
- 2019 年 10 月:
规范
实现
- 尚无