本网站上的更多内容 |
简介 |
正则表达式快速入门 |
正则表达式教程 |
替换字符串教程 |
应用程序和语言 |
正则表达式示例 |
正则表达式参考 |
替换字符串参考 |
书评 |
可打印 PDF |
关于本网站 |
RSS 源和博客 |
关于 反向引用 的上一主题适用于所有正则表达式风格,除了少数根本不支持反向引用的风格。当您开始做一些不符合“匹配先前捕获组匹配的文本”工作描述的事情时,不同风格的行为会有所不同。
引用未匹配的捕获组和根本未参与匹配的捕获组之间存在差异。正则表达式 (q?)b\1 匹配 b。 q? 是可选的,并且不匹配任何内容,导致 (q?) 成功匹配并捕获空内容。 b 匹配 b,并且 \1 成功匹配组捕获的空内容。
在大多数情况下,正则表达式 (q)?b\1 无法匹配 b。 (q) 完全无法匹配,因此该组根本无法捕获任何内容。由于整个组是可选的,因此引擎会继续匹配 b。引擎现在到达 \1,它引用了一个根本未参与匹配尝试的组。这会导致反向引用完全无法匹配,从而模拟组的结果。由于没有 ? 使 \1 可选,因此整体匹配尝试失败。
少数例外之一是 JavaScript。根据官方 ECMA 标准,对未参与捕获组的反向引用必须成功匹配空内容,就像对捕获空内容的参与组的反向引用一样。换句话说,在 JavaScript 中,(q?)b\1 和 (q)?b\1 都匹配 b。 XPath 也以这种方式工作。
Dinkumware 对 std::regex 的实现处理反向引用,就像 JavaScript 处理所有支持反向引用的语法一样。 Boost 在 1.46 版之前也是如此。从 1.47 版开始,Boost 在使用 ECMAScript 语法时会使反向引用失败到未参与的组,但在使用基本和 grep 语法时仍允许它们成功匹配空内容。
对不存在的组的反向引用,例如 (one)\7,在大多数正则表达式风格中都是一个错误。不过也有例外。JavaScript 将 \1 到 \7 视为 八进制转义,当正则表达式中的捕获组少于反斜杠后的数字时。\8 和 \9 是错误的,因为 8 和 9 不是有效的八进制数字。
Java 将对不存在的组的反向引用视为对存在但从未参与匹配的组的反向引用。它们不是错误,但根本不匹配任何内容。
.NET 稍微复杂一些。.NET 支持个位数和两位数反向引用以及不带前导零的两位数八进制转义。反向引用优先于八进制转义。因此,在捕获组少于 12 个的正则表达式中,\12 是换行符(八进制 12 = 十进制 10)。在捕获组为 12 个或更多个的正则表达式中,它将是对第 12 个组的反向引用。.NET 不支持个位数八进制转义。因此,在捕获组少于 7 个的正则表达式中,\7 是一个错误。
包括 JGsoft、.NET、Java、Perl、PCRE、PHP、Delphi 和 Ruby 在内的许多现代正则表达式风格允许前向引用。它们允许你使用对正则表达式中稍后出现的组的反向引用。前向引用显然只有在它们位于重复组内时才有用。然后,在某些情况下,正则表达式引擎可以在组已经匹配后评估反向引用。在尝试组之前,反向引用会像对失败组的反向引用一样失败。
如果支持前向引用,正则表达式 (\2two|(one))+ 将匹配 oneonetwo。在字符串的开头,\2 失败。尝试另一个 备选方案,one 由第二个捕获组匹配,随后由第一个组匹配。然后重复第一个组。这一次,\2 匹配由第二个组捕获的 one。然后 two 匹配 two。通过两次重复第一个组,正则表达式匹配了整个主题字符串。
JavaScript 不支持前向引用,但不会将它们视为错误。在 JavaScript 中,前向引用始终找到零长度匹配,就像 JavaScript 中对非参与组的反向引用一样。由于这并不是特别有用,XRegExp 将它们视为错误。在 std::regex、Boost、Python、Tcl 和 VBScript 中,前向引用是一个错误。
嵌套引用是捕获组内部的反向引用,它引用了它本身。与前向引用一样,嵌套引用仅在它们位于重复组内时才有用,如 (\1two|(one))+。当支持嵌套引用时,此正则表达式也匹配 oneonetwo。在字符串的开头,\1 失败。尝试另一个 备选方案,one 由第二个捕获组匹配,随后由第一个组匹配。然后重复第一个组。这一次,\1 匹配第一个组的最后一次迭代捕获的 one。正则表达式引擎重新进入第一个组并不重要。当组之前退出时,组匹配的文本已存储到反向引用中。然后 two 匹配 two。通过两次重复第一个组,正则表达式匹配了整个主题字符串。如果您在匹配后从捕获组中检索文本,第一个组将存储 onetwo,而第二个组将捕获字符串中 one 的第一次出现。
所有 JGsoft、.NET、Java、Perl 和 VBScript 风格都支持嵌套引用。PCRE 也支持,但存在回溯到带有嵌套反向引用的捕获组的错误。PCRE 8.01 没有修复错误,而是通过强制带有嵌套引用的捕获组为 原子来解决这些错误。因此,在 PCRE 中,(\1two|(one))+ 与 (?>(\1two|(one)))+ 相同。这会影响基于 PCRE 的正则表达式引擎的语言,例如 PHP、Delphi 和 R。
JavaScript 和 Ruby 不支持嵌套引用,而是将它们视为对非参与组的回引,而不是错误。在 JavaScript 中,这意味着它们始终匹配一个零长度字符串,而在 Ruby 中,它们始终无法匹配。在 std::regex、Boost、Python 和 Tcl 中,嵌套引用是一个错误。
| 快速入门 | 教程 | 工具和语言 | 示例 | 参考 | 书评 |
| 简介 | 目录 | 特殊字符 | 不可打印字符 | 正则引擎内部 | 字符类 | 字符类减法 | 字符类交集 | 简写字符类 | 点 | 锚点 | 单词边界 | 交替 | 可选项 | 重复 | 分组和捕获 | 回引 | 回引,第 2 部分 | 命名组 | 相对回引 | 分支重置组 | 自由间距和注释 | Unicode | 模式修饰符 | 原子分组 | 独占量词 | 前瞻和后顾 | 前瞻和后顾,第 2 部分 | 将文本保留在匹配之外 | 条件 | 平衡组 | 递归 | 子例程 | 无限递归 | 递归和量词 | 递归和捕获 | 递归和回引 | 递归和回溯 | POSIX 方括号表达式 | 零长度匹配 | 继续匹配 |
页面 URL:https://regexper.cn/backref2.html
页面上次更新时间:2019 年 11 月 22 日
网站上次更新时间:2024 年 3 月 15 日
版权所有 © 2003-2024 Jan Goyvaerts。保留所有权利。