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/4/proposal-regex-escaping.md.
  • 简体中文
  • RegExp.escape S4

    提案概览
    提案速览

    该提案引入了一个静态的 RegExp.escape 函数,用于转义字符串以便在正则表达式中字面使用,解决了避免特殊字符被解释为正则表达式的常见需求。该提案也探索了模板标签的替代方案,但拒绝了它,而选择了更简单的函数,该函数被广泛需求并在许多其他语言中实现。

    Note

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

    RegExp 转义提案

    这个 ECMAScript 提案旨在研究将字符串转义以便在正则表达式中使用的问题领域。

    正式规范

    提案发起人:

    状态

    这个提案是一个 第 4 阶段提案

    动机

    通常,当我们想用字符串构建正则表达式而不将字符串中的特殊字符视为正则表达式的特殊标记时,就会遇到这种情况。例如,如果我们想替换从用户那里获得的字符串 let text = "Hello." 的所有出现,我们可能会尝试 ourLongText.replace(new RegExp(text, "g"))。但是,这会将 . 匹配为任意字符,而不是匹配句点。

    这是常见的需求,如 这个多年前的 es-discuss 线程 所示。将其标准化对开发者非常有用,并避免他们可能创建的、可能遗漏边缘情况的劣质实现。

    选择的解决方案:

    RegExp.escape 函数

    这将是一个 RegExp.escape 静态函数,使得字符串可以被转义以便在正则表达式中使用:

    const str = prompt("请输入一个字符串");
    const escaped = RegExp.escape(str);
    const re = new RegExp(escaped, 'g'); // 处理正则表达式特殊标记,进行替换。
    console.log(ourLongText.replace(re));

    注意示例字符串内容中的双反斜杠,它们渲染为单个反斜杠。

    RegExp.escape("The Quick Brown Fox"); // "\\x54he\\x20Quick\\x20Brown\\x20Fox"
    RegExp.escape("Buy it. use it. break it. fix it.") // "\\x42uy\\x20it\\.\\x20use\\x20it\\.\\x20break\\x20it\\.\\x20fix\\x20it\\."
    RegExp.escape("(*.*)"); // "\\(\\*\\.\\*\\)"
    RegExp.escape("。^・ェ・^。") // "。\\^・ェ・\\^。"
    RegExp.escape("😊 *_* +_+ ... 👍"); // "😊\\x20\\*_\\*\\x20\\+_\\+\\x20\\.\\.\\.\\x20👍"
    RegExp.escape("\\d \\D (?:)"); // "\\\\d\\x20\\\\D\\x20\\(\\?\\x3a\\)"

    跨领域问题

    根据 https://gist.github.com/bakkot/5a22c8c13ce269f6da46c7f7e56d3c3f ,我们现在转义任何可能导致“上下文转义”的内容。

    这将承诺仅使用空白或 ASCII 标点符号进入/退出新上下文。这似乎不会显著阻碍语言的发展。

    考虑的其他解决方案:

    模板标签函数

    例如,这可以是一个模板标签函数 RegExp.tag,用于生成完整的正则表达式,而不是可能只是其中一部分:

    const str = prompt("请输入一个字符串");
    const re = RegExp.tag`/${str}/g`;
    console.log(ourLongText.replace(re));

    在其他语言中

    请注意,这些语言的做法有所不同(例如,Perl 做的事情与 C# 不同),但它们都有相同的目标。

    我们曾 就这个主题开过会,其笔记包含了对其他语言做什么以及优缺点的更详细说明。

    常见问题

    • 为什么每个转义字符都被转义?

      参见 [https://gist.github.com/bakkot/5a22c8c13ce269f6da46c7f7e56d3c3f]。

    • 如何处理 Unicode?

      这个提案处理的是码点而不是码元,因此进一步的扩展和处理 Unicode 已完成。

    • RegExp.unescape 呢?

      虽然其他一些语言提供了 unescape 方法,但我们选择将关于它的讨论推迟到以后,主要是因为没有证据表明有人要求它(而 RegExp.escape 经常被要求)。

    • 这与 EscapeRegExpPattern 抽象操作有什么关系?

      EscapeRegExpPattern(顾名思义)接受一个模式并将其转义,以便它可以表示为字符串。RegExp.escape 所做的是接受一个字符串并将其转义,以便它可以字面上表示为模式。两者不需要共享转义集合,我们不能用一个代替另一个。我们正在讨论将来在规范中重命名 EscapeRegExpPattern,以避免读者混淆。

    • 为什么不采用 RegExp.tag 或另一个基于模板标签的提案?

      在这个提案首次提出时,有人提出了标签模板作为替代方案。我们认为在这里使用简单函数比标签模板更好、更简单:

      • 在过去 5 年里,用户一直在要求 RegExp.escape - 既在这个仓库里也在其他地方。提供此功能的包非常受欢迎(参见 escape-string-regexpescape-regexp)。相比之下,当我开始研究标签提案时,没有下载,而且 几乎零问题或兴趣
      • 在采访用户关于 RegExp.tag 以试图获得 API 的激励用例时,接受采访的用户因为标签模板而感到非常困惑。反馈足够负面,他们发现 API 足够令人困惑和尴尬,以至于我停止了追求它。
      • 几乎每种其他编程语言都提供了 .escape(参见“在其他语言中”),并且即使其中大多数本可以提供标签模板 API(每种语言等价),也做出了发布 .escape 的权衡。
      • 这个提案不会阻碍标签提案的工作,这两个提案不是互斥的,两个 API 最终都可以落地。 参见 这个问题 进行讨论。
    • 为什么不直接实现 X?

      如果你认为还有未解决的担忧,请 开一个问题

    Polyfills