对失败组的反向引用对失败组的反向引用对失败组的反向引用对失败组的反向引用
  • 文章
  • 正则表达式
    • 工具
  • 登录
找到的结果: {phrase} (显示: {results_count} 共: {results_count_total})
显示: {results_count} 共: {results_count_total}

加载更多搜索结果...

搜索范围
模糊匹配
搜索标题
搜索内容
发表 admin at 2024年3月5日
类别
  • 正则表达式
标签
对失败组的反向引用
  • 简
  • 繁
  • En
关于正则表达式 » 正则表达式教程 » 对失败组的反向引用

正则表达式教程
介绍
目录
特殊字符
不可见字符
正则引擎内部
字符类
字符类减法
字符类交集
速记字符类
点
锚点
单词边界
替换
可选项目
重复
分组和捕获
反向引用
反向引用,第2部分
命名组
相对反向引用
分支重置组
自由间隔和注释
Unicode
模式修饰符
原子分组
占有量词
先行断言和后行断言
环绕,第2部分
保持文本不匹配
条件
平衡组
递归
子进程
无限递归
递归和量词
递归和捕获
递归和反向引用
递归和回溯
POSIX括号表达式
零长度匹配
持续匹配
本站更多信息
介绍
正则表达式快速入门
正则表达式教程
替换字符串教程
应用与语言
正则表达式示例
正则表达式参考
替换字符串参考

对失败组的反向引用

前一主题反向引用适用于所有正则表达式风格,除了那些根本不支持反向引用的少数风格。当您开始做一些不符合“匹配以前捕获组所匹配的文本”的工作时,风格会表现出不同的行为。

反向引用到一个未匹配任何内容的捕获组和到根本没有参与匹配的捕获组之间存在区别。正则表达式 (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也是这样工作的。

std::regex的Dinkumware实现对于支持回溯引用的所有语法都像JavaScript一样处理回溯引用。直到版本1.46,Boost也是如此。从版本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

向前参照

许多现代正规表达式(regex)引擎,包括.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 的出现。

.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 中,嵌套参考是一个错误。

對失敗組的反向引用
  • 简
  • 繁
  • En
關於正規表示式 » 正規表示式教學 » 對失敗組的反向引用

正則表達式教程
介紹
目錄
特殊字符
不可見字符
正則引擎內部
字符類
字符類減法
字符類交集
速記字符類
點
錨點
單詞邊界
替換
可選項目
重複
分組和捕獲
反向引用
反向引用,第2部分
命名組
相對反向引用
分支重置組
自由間隔和注釋
Unicode
模式修飾符
原子分組
佔有量詞
先行斷言和後行斷言
環繞,第2部分
保持文本不匹配
條件
平衡組
遞歸
子程序
無限遞歸
遞歸和量詞
遞歸和捕獲
遞歸和反向引用
遞歸和回溯
POSIX括號表達式
零長度匹配
持續匹配
本站更多資訊
介紹
正則表達式快速入門
正則表達式教程
替換字符串教程
應用與語言
正則表達式示例
正則表達式參考
替換字符串參考

對失敗組的反向引用

前一主題反向引用適用於所有正則表達式風格,除了那些根本不支援反向引用的少數風格。當您開始做一些不符合“匹配以前捕獲組所匹配的文本”的工作時,風格會表現出不同的行為。

反向引用到一個未匹配任何內容的捕獲組和到根本沒有參與匹配的捕獲組之間存在區別。正則表達式 (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也是這樣工作的。

std::regex的Dinkumware實現對於支持回溯引用的所有語法都像JavaScript一樣處理回溯引用。直到版本1.46,Boost也是如此。從版本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

向前參照

許多現代正規表達式(regex)引擎,包括.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 的出現。

.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 中,嵌套參考是一個錯誤。

Backreferences to Failed Groups
  • 简
  • 繁
  • En
About Regular Expressions » Regular Expressions Tutorial » Backreferences to Failed Groups

Regex Tutorial
Introduction
Table of Contents
Special Characters
Non-Printable Characters
Regex Engine Internals
Character Classes
Character Class Subtraction
Character Class Intersection
Shorthand Character Classes
Dot
Anchors
Word Boundaries
Alternation
Optional Items
Repetition
Grouping & Capturing
Backreferences
Backreferences, part 2
Named Groups
Relative Backreferences
Branch Reset Groups
Free-Spacing & Comments
Unicode
Mode Modifiers
Atomic Grouping
Possessive Quantifiers
Lookahead & Lookbehind
Lookaround, part 2
Keep Text out of The Match
Conditionals
Balancing Groups
Recursion
Subroutines
Infinite Recursion
Recursion & Quantifiers
Recursion & Capturing
Recursion & Backreferences
Recursion & Backtracking
POSIX Bracket Expressions
Zero-Length Matches
Continuing Matches
More on This Site
Introduction
Regular Expressions Quick Start
Regular Expressions Tutorial
Replacement Strings Tutorial
Applications and Languages
Regular Expressions Examples
Regular Expressions Reference
Replacement Strings Reference

Backreferences to Failed Groups

The previous topic on backreferences applies to all regex flavors, except those few that don’t support backreferences at all. Flavors behave differently when you start doing things that don’t fit the “match the text matched by a previous capturing group” job description.

There is a difference between a backreference to a capturing group that matched nothing, and one to a capturing group that did not participate in the match at all. The regex (q?)b\1 matches b. q? is optional and matches nothing, causing (q?) to successfully match and capture nothing. b matches b and \1 successfully matches the nothing captured by the group.

In most flavors, the regex (q)?b\1 fails to match b. (q) fails to match at all, so the group never gets to capture anything at all. Because the whole group is optional, the engine does proceed to match b. The engine now arrives at \1 which references a group that did not participate in the match attempt at all. This causes the backreference to fail to match at all, mimicking the result of the group. Since there’s no ? making \1 optional, the overall match attempt fails.

One of the few exceptions is JavaScript. According to the official ECMA standard, a backreference to a non-participating capturing group must successfully match nothing just like a backreference to a participating group that captured nothing does. In other words, in JavaScript, (q?)b\1 and (q)?b\1 both match b. XPath also works this way.

Dinkumware’s implementation of std::regex handles backreferences like JavaScript for all its grammars that support backreferences. Boost did so too until version 1.46. As of version 1.47, Boost fails backreferences to non-participating groups when using the ECMAScript grammar, but still lets them successfully match nothing when using the basic and grep grammars.

Backreferences to Non-Existent Capturing Groups

Backreferences to groups that do not exist, such as (one)\7, are an error in most regex flavors. There are exceptions though. JavaScript treats \1 through \7 as octal escapes when there are fewer capturing groups in the regex than the digit after the backslash. \8 and \9 are an error because 8 and 9 are not valid octal digits.

Java treats backreferences to groups that don’t exist as backreferences to groups that exist but never participate in the match. They are not an error, but simply never match anything.

.NET is a little more complicated. .NET supports single-digit and double-digit backreferences as well as double-digit octal escapes without a leading zero. Backreferences trump octal escapes. So \12 is a line feed (octal 12 = decimal 10) in a regex with fewer than 12 capturing groups. It would be a backreference to the 12th group in a regex with 12 or more capturing groups. .NET does not support single-digit octal escapes. So \7 is an error in a regex with fewer than 7 capturing groups.

Forward References

Many modern regex flavors, including .NET, Java, Perl, PCRE, PHP, Delphi, and Ruby allow forward references. They allow you to use a backreference to a group that appears later in the regex. Forward references are obviously only useful if they’re inside a repeated group. Then there can be situations in which the regex engine evaluates the backreference after the group has already matched. Before the group is attempted, the backreference fails like a backreference to a failed group does.

If forward references are supported, the regex (\2two|(one))+ matches oneonetwo. At the start of the string, \2 fails. Trying the other alternative, one is matched by the second capturing group, and subsequently by the first group. The first group is then repeated. This time, \2 matches one as captured by the second group. two then matches two. With two repetitions of the first group, the regex has matched the whole subject string.

JavaScript does not support forward references, but does not treat them as an error. In JavaScript, forward references always find a zero-length match, just as backreferences to non-participating groups do in JavaScript. Because this is not particularly useful, XRegExp makes them an error. In std::regex, Boost, Python, Tcl, and VBScript forward references are an error.

Nested References

A nested reference is a backreference inside the capturing group that it references. Like forward references, nested references are only useful if they’re inside a repeated group, as in (\1two|(one))+. When nested references are supported, this regex also matches oneonetwo. At the start of the string, \1 fails. Trying the other alternative, one is matched by the second capturing group, and subsequently by the first group. The first group is then repeated. This time, \1 matches one as captured by the last iteration of the first group. It doesn’t matter that the regex engine has re-entered the first group. The text matched by the group was stored into the backreference when the group was previously exited. two then matches two. With two repetitions of the first group, the regex has matched the whole subject string. If you retrieve the text from the capturing groups after the match, the first group stores onetwo while the second group captured the first occurrence of one in the string.

.NET, Java, Perl, and VBScript flavors all support nested references. PCRE does too, but had bugs with backtracking into capturing groups with nested backreferences. Instead of fixing the bugs, PCRE 8.01 worked around them by forcing capturing groups with nested references to be atomic. So in PCRE, (\1two|(one))+ is the same as (?>(\1two|(one)))+. This affects languages with regex engines based on PCRE, such as PHP, Delphi, and R.

JavaScript and Ruby do not support nested references, but treat them as backreferences to non-participating groups instead of as errors. In JavaScript that means they always match a zero-length string, while in Ruby they always fail to match. In std::regex, Boost, Python, and Tcl, nested references are an error.

©2015-2025 艾丽卡 support@alaica.com