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/pending/proposal-regexp-atomic-operators.md.
  • 简体中文
  • RegExp Atomic Operators S1

    中文标题:正则表达式原子运算符

    提案概览
    提案速览

    本提案为 ECMAScript 正则表达式引入原子组和占有量词,以控制回溯,防止灾难性回溯并提升性能。原子组(如 (?>bc\|b))在成功匹配后丢弃回溯信息,而占有量词(如 *+++)是原子组的语法糖。

    Note

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

    用于 ECMAScript 的正则表达式原子运算符

    本提案旨在为 ECMAScript 正则表达式引入语法,通过将模式的某些部分视为“原子”,在特定场景下控制回溯:当这部分匹配成功时,其回溯信息将被丢弃。

    例如,当前模式 a(bc|b)c 能匹配 "abcc""abc" 两种情况。对于 "abcc",我们匹配 a,然后匹配备选分支 bc,最后匹配 c。对于 "abc",我们匹配 a,然后匹配备选分支 bc(消耗了全部输入),但最后匹配 c 失败。由于后续匹配失败,我们 回溯 到析取 bc|b 的开头,尝试备选分支 b。然后我们匹配 b,最后匹配 c

    在某些情况下,这种回溯是不需要的,甚至可能是灾难性的。为解决此类问题,我们提议添加 原子组(?> Disjunction ))和 占有量词n*+n++ 等)。在原子组中,如果组匹配成功,其回溯信息将被丢弃。如果原子组之后的模式匹配失败,我们将不再回溯到组的开头尝试备选分支。

    对于 a(?>bc|b)c,我们仍会匹配 "abcc",但不会匹配 "abc"。对于 "abc",我们匹配 a,然后匹配备选分支 bc,但匹配 c 失败。由于析取 bc|b 在成功匹配 bc 后回溯信息已被丢弃,我们无法尝试备选分支 b。因此,对于 "abc" 的匹配失败。

    值得注意的是,环视运算符(即 (?=)(?!)(?<=)(?<!))已经是原子操作。

    状态

    阶段: 1
    提案负责人: Ron Buckton (@rbuckton)

    有关本提案的详细状态,请参见下面的 TODO

    作者

    动机

    注意:请参阅 https://github.com/rbuckton/proposal-regexp-features 以了解本提案如何与其他可能的正则表达式未来特性相协调。

    本提案旨在引入新语法,让用户能够通过占有量词和回溯控制来精细控制正则表达式的性能特征。

    已有实现

    请参阅 https://rbuckton.github.io/regexp-features/features/possessive-quantifiers.htmlhttps://rbuckton.github.io/regexp-features/features/non-backtracking-expressions.html 获取更多信息。

    语法

    原子组

    原子组是一个非回溯表达式,其匹配独立于相邻模式,并且在匹配失败时不会回溯。这通常用于提高性能。

    • (?>pattern) — 匹配提供的模式,但如果匹配失败,则不再进行回溯。

    注意:此语法与现有语法没有冲突,因为 ECMAScript 目前对 u 模式和非 u 模式下的此语法都会产生错误。

    占有量词

    占有量词与普通(即“贪婪”)量词类似,但如果右侧的模式的其余部分匹配失败,则不会回溯。占有量词通常用作性能调整,以避免灾难性回溯。

    • *+ — 匹配前一个原子的零个或多个实例,且不回溯。
    • ++ — 匹配前一个原子的一个或多个实例,且不回溯。
    • ?+ — 匹配前一个原子的零个或一个实例,且不回溯。
    • {n}+ — 其中 n 是整数。精确匹配前一个原子的 n 次,且不回溯。
    • {n,}+ — 其中 n 是整数。匹配前一个原子的至少 n 次,且不回溯。
    • {n,m}+ — 其中 nm 是整数,且 m >= n。匹配前一个原子的至少 n 次且至多 m 次,且不回溯。

    注意:此语法与现有语法没有冲突,因为 ECMAScript 目前对 u 模式和非 u 模式下此语法都会产生错误。

    占有量词是 (?> Disjunction ) 的语法糖:

    • atom*+ 等价于 (?>atom*)
    • atom++ 等价于 (?>atom+)
    • atom?+ 等价于 (?>atom?)
    • atom{n}+ 等价于 (?>atom{n})
    • atom{n,}+ 等价于 (?>atom{n,})
    • atom{n,m}+ 等价于 (?>atom{n,m})

    示例

    // 注意:使用 x 模式标志来说明差异
    // 没有原子组:
    const re1 = /\((      [^()]+   | \([^()]*\))+ \)/x;
    re1.test("((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); // 可能需要几秒钟才能失败
    
    // 使用原子组
    const re2 = /\((  (?> [^()]+ ) | \([^()]*\))+ \)/x;
    //                ^^^--------^ 原子组
    re2.test("((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); // 由于涉及更少的回溯,速度显著提升
    
    // 使用占有量词
    const re2 = /\((      [^()]++  | \([^()]*\))+ \)/x;
    //                         ^^- 占有量词
    re2.test("((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); // 由于涉及更少的回溯,速度显著提升

    有关 x 标志的更多信息,请参阅 https://github.com/rbuckton/proposal-regexp-x-mode。

    历史

    TODO

    以下是推进 TC39 提案流程 各阶段所需任务的高级列表:

    Stage 1 进入标准

    • 确定了一位将推进此增强的“提案负责人”。
    • 提供 散文 概述问题或需求以及解决方案的大致形状。
    • 提供说明性的使用 示例
    • 高级 API

    Stage 2 进入标准

    Stage 3 进入标准

    Stage 4 进入标准

    • 已为主要使用场景编写 Test262 验收测试并 合并
    • 两个通过验收测试的兼容实现:[1][2]
    • 已向 tc39/ecma262 发送包含集成规范文本的 拉取请求
    • ECMAScript 编辑已签署该 拉取请求