For AI agents: the complete documentation index is available at /tc39-atlas/llms.txt, the full documentation bundle is available at /tc39-atlas/llms-full.txt, and this page is available as Markdown at /tc39-atlas/proposals/stage/unstaged/proposal-regexp-unicode-sequence-properties.md.
  • 简体中文
  • Sequence properties in Unicode property escapes ?

    中文标题:Unicode 属性转义中的字符串序列属性

    提案概览
    提案速览

    该提案解决了 Unicode 属性转义仅支持扩展为码点集的属性,而不支持多字符字符串的限制。它建议重用现有的 \\p{.} 语法来支持几个 Unicode 序列属性,如 RGI_Emoji_ZWJ_Sequence,从而能够匹配 emoji 序列。

    Note

    以下 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 字符属性。

    const regexGreek = /\p{Script=Greek}/u;
    regexGreek.test('π');
    // → true

    在 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|Wxyz|xy|[a-cW]。(最长的字符串在前,这样如 'xy' 这样的前缀不会隐藏如 'xyz' 这样的更长字符串。)请注意,与现有 Unicode 属性转义不同,此模式可以匹配多字符字符串。

    手写的这些属性的正则表达式会遭受与 Unicode 属性转义所解决的相同问题:它们难以手动编写或维护,往往体积较大,且可读性差。

    提议的解决方案

    我们提议在现有的 Unicode 属性转义语法中增加若干_字符串属性_。

    有了此功能,上述正则表达式可以写成:

    const re = /\p{RGI_Emoji_ZWJ_Sequence}/u;
    re.test('👨🏾‍⚕️'); // '\u{1F468}\u{1F3FE}\u200D\u2695\uFE0F'
    // → true

    我们提议支持以下在 UTS18UTS51 中定义的 Unicode 序列属性:

    • Basic_Emoji
    • Emoji_Keycap_Sequence
    • RGI_Emoji_Modifier_Sequence
    • RGI_Emoji_Flag_Sequence
    • RGI_Emoji_Tag_Sequence
    • RGI_Emoji_ZWJ_Sequence
    • RGI_Emoji

    这些序列属性中的每一个都扩展为一个有限的、定义明确的字符串集合。(Basic_Emoji 也适用于许多单个字符。)

    随着时间推移,我们可以选择支持额外的字符串属性,遵循上游 Unicode 标准。

    高级 API

    对这个新功能重用现有的 Unicode 属性转义语法似乎是合适的:

    \p{PropertyName}

    其中 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 模式:

    const reRgiEmoji = /\p{RGI_Emoji}/u;

    不使用属性转义的等价正则表达式 大小约为 7 kB。使用属性转义但不支持字符串属性,大小约为 4.5 kB。上述带序列属性的正则表达式仅占 16 字节。

    匹配 hashtags

    许多应用程序(如 Twitter)使用允许 emoji 字符的扩展 hashtag。Unicode® 标准附录 #31 定义了 扩展 Hashtag 标识符语法 (UAX31-R8) 为匹配:

    // 来自 UAX #31,不是 JavaScript 语法。
    /[#﹟#][\p{XID_Continue}\p{Extended_Pictographic}\p{Emoji_Component}[-+_]-[#﹟#]]+/

    上述模式匹配 emoji,但也匹配语法上无效的 emoji 以及不推荐用于通用交换的 emoji。然而,有了提议的功能,匹配仅包含有效和推荐 emoji 的 hashtag 变得可行:

    const reHashtag = /[#﹟#][[\p{XID_Continue}\p{RGI_Emoji}[-+_]]--[#﹟#]]+/u;

    不使用属性转义的等价正则表达式 大小约为 12 kB。使用属性转义但不支持字符串属性,大小约为 3 kB。上述带序列属性的正则表达式仅占 62 字节。

    相关的 UTC 提案

    TC39 会议记录

    规范

    实现

    • 尚无