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/year/2024/proposal-regexp-v-flag.md.
  • 简体中文
  • RegExp v flag with set notation + properties of strings S4

    中文标题:带有集合表示法和字符串属性的 RegExp v 标志

    提案概览
    提案速览

    该提案为 ECMAScript 正则表达式添加了一个新的 v 标志,支持集合表示法,如差集(A--B)、交集(A&&B)和嵌套字符类,以及字符类中的字符串属性和字符串字面量。它解决了对表现力丰富的字符类组合和 Unicode 字符串属性的需求,改进了现有 u 标志的有限语法和不区分大小写匹配。

    Note

    以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。

    ECMAScript 提案:带有集合表示法和字符串属性的 RegExp v 标志

    作者

    • Markus Scherer
    • Mathias Bynens

    状态

    该提案在 2023 年 5 月 16 日的会议中达到了 TC39 流程 的第 4 阶段。它于 2023 年 6 月 15 日被 合并ECMAScript 规范 中,有望纳入 ECMAScript 2024 快照。

    截至 2021 年 5 月 25 日的 TC39 会议,该提案正式包含了 字符串属性提案

    摘要

    在 ECMAScript 正则表达式字符类中,我们提议添加以下集合运算的语法和语义:

    • 差集/减法(在 A 中但不在 B 中
    • 交集(同时在 A 和 B 中
    • 嵌套字符类(为实现上述功能所必需

    此外,通过与 字符串属性提案 的合并,我们还提议添加某些 Unicode 字符串属性,以及字符类中的字符串字面量。

    面向 JavaScript 开发者的提案解释,请参见 我们在 v8.dev 上的特性文章

    动机

    许多正则表达式引擎支持命名属性字符,主要反映 Unicode 字符属性,以避免硬编码可能需要数百个范围且可能随 Unicode 新版本变化的字符类。

    然而,一个字符属性往往只是起点。常见的需求包括添加(并集)、排除(差集)和“同时满足此和彼”(交集)。参见 UTS #18:Unicode 正则表达式 中支持集合运算的建议。

    ECMAScript 正则表达式模式已经以有限形式支持一种集合运算:可以创建字符、范围和类的并集,只要这些类是像 \s\p{Decimal_Number} 这样的 CharacterClassEscape

    在网络上搜索有关此类集合运算的正则表达式问题,会发现一些变通方法,例如硬编码集合运算产生的范围(失去命名属性的好处)和先行断言(对此目的不直观且性能较差)。

    我们提议添加差集和交集以及嵌套字符类的语法和语义。

    拟议解决方案

    我们提议扩展字符类的语法,以支持集合差集/减法、集合交集和嵌套字符类。

    高层 API

    在正则表达式模式中,我们提议启用以下功能。

    // 差集/减法
    [A--B]
    
    // 交集
    [A&&B]
    
    // 嵌套字符类
    [A--[0-9]]

    在这些高层示例中,AB 可以看作是字符类(例如 [a-z])或属性转义(例如 \p{ASCII})的占位符,可能(取决于具体讨论)是单字符和/或字符范围。参见 说明性示例部分 中的具体实际用例。

    说明性示例

    来自使用 ICU UnicodeSet 的代码的实际示例,它实现了类似于正则表达式字符类的模式语法(此处修改为使用 \p{Perl syntax for properties} 而不是 [:POSIX syntax for properties:]UnicodeSet 两者都支持):

    • 查找非 ASCII 数字以将其转换为 ASCII 数字:

      [\p{Decimal_Number}--[0-9]]
    • 查找特定文字的“单词/标识符字母”范围:

      [\p{Script=Khmer}&&[\p{Letter}\p{Mark}\p{Number}]]
    • 查找“分隔空格”:

      [\p{White_Space}--\p{Line_Break=Glue}]

      注意,ECMAScript 目前不支持 \p{Line_Break=…} — 这只是一个说明性示例。

    • 查找除 ASCII 表情符号之外的 emoji 字符:

      [\p{Emoji}--[#*0-9]]
      
      // …或…
      
      [\p{Emoji}--\p{ASCII}]
    • 查找非特定文字的组合标记:

      [\p{Nonspacing_Mark}&&[\p{Script=Inherited}\p{Script=Common}]]
    • 查找除 ASCII 空格之外的“不可见字符”:

      [[\p{Other}\p{Separator}\p{White_Space}\p{Default_Ignorable_Code_Point}]--\x20]
    • 查找每个文字中的“首字母”,从以下开始:

      [\P{NFC_Quick_Check=No}--\p{Script=Common}--\p{Script=Inherited}--\p{Script=Unknown}]

      注意,ECMAScript 目前不支持 \p{NFC_Quick_Check=…} — 这只是一个说明性示例。

    • 所有既是字母、标记(例如变音符号)或十进制数字的希腊代码点:

      [\p{Script_Extensions=Greek}&&[\p{Letter}\p{Mark}\p{Decimal_Number}]]
    • 所有代码点,除了“其他”General_Category 中的代码点,但重新添加控制字符:

      [[\p{Any}--\p{Other}]\p{Control}]
    • 所有已分配的代码点,除了分隔符:

      [\p{Assigned}--\p{Separator}]
    • 所有从右到左和阿拉伯字母代码点,但移除未分配的代码点:

      [[\p{Bidi_Class=R}\p{Bidi_Class=AL}]--\p{Unassigned}]

      注意,ECMAScript 目前不支持 \p{Bidi_Class=…} — 这只是一个说明性示例。

    • 所有从右到左和阿拉伯字母代码点,且 General_Category 为“字母”:

      [\p{Letter}&&[\p{Bidi_Class=R}\p{Bidi_Class=AL}]]

      注意,ECMAScript 目前不支持 \p{Bidi_Class=…} — 这只是一个说明性示例。

    • General_Category 为“其他”的所有字符,除了格式和控制字符(或等效地,所有代理项、私有使用和未分配的代码点):

      [\p{Other}--\p{Format}--\p{Control}]

    常见问题解答

    新语法是否向后兼容?我们需要另一个正则表达式标志吗?

    本提案的一个明确目标是不破坏向后兼容性。具体来说,我们不想改变任何当前不抛出异常的正则表达式模式的行为。需要某种方式来指示正在使用新语法。

    我们考虑了 4 个选项:

    • 表达式外部的新标志。
    • 表达式内部的修饰符,形式为 (?L),其中 L 是一个 ASCII 字母。(多种正则表达式引擎支持类似的各种修饰符。)
    • \U… 这样的前缀,在当前 u 标志(Unicode 模式)下无效 — 但注意,没有 u 标志的 \UU 本身相同。
      • (禁止在 u 正则表达式中使用未知转义序列是 一个有意识的选择,以便支持这种扩展。)
    • (?[ 这样的前缀,在现有模式中不管标志如何都无效。

    使用前缀的想法是在早期 TC39 会议上提出的,所以我们一直在研究其变体,例如:

    UnicodeCharacterClass = '\UniSet{' ClassContents '}'

    然而,我们发现这不是非常对开发者友好。

    特别是,人们必须在 同时 使用 u 标志的情况下编写前缀。Waldemar 指出,前缀 看起来 应该足够了,因此开发者很可能意外地忘记添加 u 标志。虽然这个方面可以通过使用一个更复杂的前缀来解决,该前缀在当前无论是否使用 u 标志都是无效的(如 (?[),但这会牺牲可读性。

    此外,使用反斜杠字母前缀会希望将新语法括在 {大括号} 中,因为其他此类语法(\p{property}\u{12345} 等)使用大括号 — 但对于字符类的最外层不使用 [方括号] 看起来很奇怪。

    最后,当一个表达式中有几个新语法字符类时,每个都必须使用前缀,这很笨拙。

    表达式内部的修饰符是一个有吸引力的替代方案,但 ECMAScript 尚未使用任何此类修饰符。

    因此,新标志是指示新字符类语法的最简单、最用户友好且语法和语义上最干净的方式。它应该 隐含并基于 u 标志。

    我们建议使用标志 v,作为 u 之后的字母。

    我们还建议 拟议的字符串属性 需要使用这个相同的新标志。

    换句话说,新标志将指示几个与属性和字符类相关的连接更改:

    • 字符串属性
    • 字符类可以包含多字符字符串元素,通过字符串字面量或某些属性
    • 嵌套类
    • 集合运算符
    • 更简单的破折号和方括号解析
    • 修复/改进的 IgnoreCase 匹配

    更多讨论参见 issue 2

    v 标志与 u 标志有何不同?

    这个问题的答案在“升级”现有的 u 正则表达式以使用 v 时会很有用。以下是差异的概述:

    1. (这是明显的部分。)以前无效的模式,利用新语法(见上文)现在变得有效,例如

      [\p{ASCII_Hex_Digit}--[Ff]]
      \p{RGI_Emoji}
      [_\q{a|bc|def}]
    2. 一些以前有效的模式现在是错误,特别是那些字符类包含未转义的 特殊字符 ( ) [ { } / - |(注意:\] 在字符类内也需要转义,但在 u 标志下已经是这样了)或 双重标点符号 的模式:

      [(]
      [)]
      [[]
      [{]
      [}]
      [/]
      [-]
      [|]
      [&&]
      [!!]
      [##]
      [$$]
      [%%]
      [**]
      [++]
      [,,]
      [..]
      [::]
      [;;]
      [<<]
      [==]
      [>>]
      [??]
      [@@]
      [``]
      [~~]
      [^^^]
      [_^^]
    3. u 标志存在令人困惑的不区分大小写匹配行为。v 标志具有不同的、改进的语义。参见 解释器 了解概述,或 issue #30 了解更多详情。

    在其他正则表达式风格中有什么先例?

    其他几种正则表达式引擎以某种形式支持所提议的部分或全部扩展:

    语言/实现并集差集交集嵌套类对称差
    ICU regex
    java.util.regex.Pattern🤷 *
    Perl (“experimental feature available starting in 5.18”)
    .Net
    XML Schema
    Apache Xerces2 XPath regex
    Python regex module (not built-in "re")
    Ruby Regexp
    本提案之前的 ECMAScript
    本提案的 ECMAScript

    * 差集被 记录 为带否定的交集。仅支持否定 + 嵌套类,你已经有了交集和差集的功能等价物:[^[^ab][^cd]] === [[ab]&&[cd]][^[^ab][cd]] === [[ab]--[cd]]。这只是不够可读。因此,我们的提案包括专门用于交集和差集的语法。

    这些在语法和语义(例如运算符优先级)上都有所不同。参考资料:

    一些 Stack Overflow 讨论:

    这与 属性字符串即序列属性提案 如何交互?

    我们在通往阶段 2 的道路上描述了两个提案之间的确切交互。(背景参见 issue #3。)

    我们提议需要新标志来启用字符串属性,以及允许新语法字符类包含多字符字符串元素(来自字符串字面量或类中使用的字符串属性)。

    一个字符串属性能否变为字符属性,反之亦然?

    简短回答:不能。

    详细回答:我们在 2019 年 5 月向 Unicode 技术委员会(UTC)提出了这一点(参见 L2/19-168 + 会议记录),后来(2021 年 4 月)提出了一个具体的稳定性政策(参见 L2/21-091 + 会议记录)。UTC 达成共识批准了我们的提案。规范性或信息性 Unicode 属性的域绝不能改变。特别是,字符属性绝不能变为字符串属性,反之亦然。

    一个属性或字符类能否匹配无限字符串集?

    简短回答:不能。

    本提案,就像原始的 字符串属性提案 一样,添加了对某些字符串属性的支持,每个属性扩展为有限的、明确定义的字符串集(Basic_Emoji 也适用于许多单字符);本提案添加了显式枚举字符串的字符类语法,这也创建了一个有限集。这是对有限字符属性和有限字符类/字符集的自然扩展。

    例如,在 UTS #51 中有非常明确的区别:

    1. emoji zwj 序列通过正则表达式定义,匹配无限字符串集
    2. RGI emoji ZWJ 序列集(= RGI_Emoji_ZWJ_Sequence 属性),这是 数据文件中列出的有限字符串集

    理论上可以支持无限字符串集的命名匹配器,即一种命名子正则表达式。这明确不是本提案的一部分, 也未对此类假设表达式的语法和语义进行任何推测。

    有足够的保留语法(例如,大括号)来支持未来广泛的扩展,但我们不打算在提议的规范更改中构建具体内容。

    包含字符串的字符类的匹配顺序是什么?

    本提案确保最长的字符串首先匹配,这样像 'xy' 这样的前缀不会隐藏像 'xyz' 这样的更长字符串。例如,模式 [a-c\q{W|xy|xyz}] 适用于字符串 'a''b''c''W''xy''xyz'。这个模式的行为类似于 xyz|xy|a|b|c|Wxyz|xy|[a-cW]

    最长字符串优先匹配是与 \p{RGI_Emoji} 等字符串属性集成的关键。Unicode 属性在数学意义上定义了一组字符/字符串;特别是,没有顺序。因此,例如在 [\p{RGI_Emoji}--\q{🇧🇪}] 中没有可保留的字符串顺序。

    关于最长字符串优先匹配理由的更多细节,参见 issue #25

    一个字符类可能包含多个相同长度的字符串:例如 [xyz] 包含三个单字符字符串,[\q{xx|yy|zz}](使用新字符串字面量语法)包含三个双字符字符串。这些相同长度字符串没有固有或可观察的匹配顺序。委员会 讨论 并决定字符类是数学集,没有固有顺序。就像 [xyz][zyx] 在匹配顺序上没有可观察差异一样,[\q{xx|yy|zz}][\q{zz|yy|xx}] 在匹配顺序上也没有差异。这种细微差别使实现者可以使用集合(即数学集的实现)和字典树(检索树)进行运行时优化。

    字符串属性是贪婪/原子性的吗?

    不是。如上一个 FAQ 条目所示,\p{PropertyOfStrings} 脱糖为简单的析取,而不是包含析取的 原子组。我们认为这种行为是最面向未来的,原因如下。

    如果,作为单独提案的一部分,原子组 按照其他语言的语法先例添加到 ECMAScript,用户可以做出自己的选择,即

    • 如果希望原子行为,使用 (?>\p{PropertyOfStrings})
    • 如果希望非原子行为,使用 \p{PropertyOfStrings}

    另一方面,如果我们强制字符串属性是原子的,用户就没有办法选择退出原子行为,而无需发明一种在其他正则表达式风格中没有先例的新的“非原子”正则表达式运算符。

    参见 issue #50 了解详情。

    A--B 中,当 B 不是 A 的真子集时,减法如何表现?

    如上一个问题的答案所述,根据当前 ECMAScript 规范和其他正则表达式实现,字符类是数学集合。因此,移除原始集合中不存在的字符串不是错误,而是无操作。示例(注意 RGI_Emoji 包含字符串 🇧🇪,但 RGI_Emoji_ZWJ_Sequence 不包含):

    # 真子集。
    [\p{RGI_Emoji}--\q{🇧🇪}]
    # 不是真子集。
    [\p{RGI_Emoji_ZWJ_Sequence}--\q{🇧🇪}]

    如果其中一个模式抛出异常,那将是令人困惑且适得其反的。

    本解释器中的几个实际说明性示例 依赖这种有用的 A--B 模式,支持它至关重要。参见 issue #32 获取更多背景。

    对称差呢?

    我们也考虑过提议一个对称差运算符(参见 issue #5),但没有找到好的用例,并希望保持提案简单。

    相反,我们提议保留双写 ASCII 标点符号和符号以供将来使用。这将允许未来的提案添加例如 ~~ 用于对称差,如 UTS #18 所建议的。

    本提案是否影响 ECMAScript 词法分析?

    不影响。我们提案的明确目标是,在提案之前正确的 ECMAScript 词法分析器在提案之后仍然是正确的 ECMAScript 词法分析器。

    TC39 会议记录 + 幻灯片

    规范

    (我们最初在 Google 文档 中开发了草稿规范更改,但后来将所有更改从那里移到了拉取请求中。)

    与其他标准的集成:

    实现

    HTML pattern 属性中的 v 标志的支持 可在以下环境中使用: