【问题标题】:How does this forward regex example work?这个正则表达式示例如何工作?
【发布时间】:2017-12-23 19:14:38
【问题描述】:

如果支持前向引用,则正则表达式 (\2two|(one))+ 匹配 oneonetwo。

在字符串的开头,\2 失败。尝试另一种选择,

那么“/2”失败就意味着后面的“二”被跳过了?

一个被第二个捕获组匹配,随后被第一个组匹配。

我了解“第二个捕获组”,但它如何与“第一组”匹配?另外,如果匹配两次,为什么我们会在最终结果中得到“oneonetwo”而不是“oneoneonetwo”?

然后重复第一组。这一次,\2 匹配第二组捕获的一个。两个然后匹配两个。第一组重复两次,正则表达式匹配了整个主题字符串。

示例取自这里:

https://www.regular-expressions.info/backref2.html

【问题讨论】:

  • 这让我觉得它更像是一个脑筋急转弯,而不是你会发现自己使用的实际正则表达式。但无论如何,理解它的最好方法是使用像 www.regex101.com 这样的工具

标签: regex


【解决方案1】:

(\2two|(one))+对应如下指令:

(    # start recording (for capture buffer 1)
    \2   # match the string that is stored in capture buffer 2
    two  # match "two" literally
  |    # or
    (    # start recording (for capture buffer 2)
    one  # match "one" literally
    )    # stop recording; set capture buffer 2
)    # stop recording; set capture buffer 1
+    # repeat the previous thing 1 or more times

假设目标字符串是oneonetwo。接下来会发生什么?

我们从目标字符串的偏移量 0 和正则表达式的开头开始。

逻辑上首先要执行的是+;它是正则表达式中的顶级操作。它尝试重复匹配其子正则表达式(1 次或多次)。

( 开始记录捕获缓冲区 1,但实际上并没有做任何其他事情。

\2 尝试匹配来自捕获缓冲区 2 的字符串,但未设置捕获缓冲区 2。这就像一个从不匹配的字符串,所以整个第一个替代方案都无法匹配。

| 启动,我们尝试第二种选择。

( 开始记录捕获缓冲区 2。

我们尝试匹配 one 并成功:在目标字符串的偏移量 0 处有一个 one。我们增加我们在字符串中的位置(剩余字符:onetwo)并继续匹配。

) 停止录制;捕获缓冲区 2 现在设置为 one

) 停止录制;捕获缓冲区 1 现在设置为 one

我们的第一次循环迭代是成功的。我们尝试匹配更多(因为这就是 + 所做的):

( 开始记录捕获缓冲区 1(再次)。

\2 尝试匹配来自捕获缓冲区 2 的字符串,现在是 one。这成功了,因为在目标字符串的当前偏移量处有一个one。我们增加我们在字符串中的位置(剩余字符:two)并继续匹配。

我们尝试匹配two 并成功。我们在目标字符串中的位置现在位于最后。

| 看到第一个替代方案成功;我们暂时忽略另一种选择。

) 停止录制;捕获缓冲区 1 现在设置为 onetwo

循环的第二次迭代到此结束。我们再次尝试匹配更多:

( 开始记录捕获缓冲区 1。

\2 尝试匹配来自捕获缓冲区 2 的字符串,该字符串仍然是 one。这失败了(目标字符串中没有字符了)。

| 启动,我们尝试第二种选择。

( 开始记录捕获缓冲区 2。

我们尝试匹配 one 并再次失败(目标字符串中没有剩余字符)。

第二个选择不匹配,所以整个子组失败(我们丢弃了我们为捕获缓冲区 2 开始的最后一个记录)。

控制权返回+。我们已经匹配了循环的两次完整迭代(第三次失败)。这很好(两个是“1 或更多”的完美实例)。

我们继续,到达正则表达式的末尾。这意味着整个正则表达式匹配成功。最后,捕获缓冲区1包含onetwo,捕获缓冲区2包含one

具体来说:

oneonetwo
^^^ #1
^^^ #2

^ 第一次迭代后。

oneonetwo
   ^^^^^^ #1
^^^ #2

^ 第二次迭代后。

【讨论】:

  • 捕获组缓冲区是否从一个匹配到下一个匹配?
  • @TimBiegeleisen 取决于您所说的“匹配”。 :-) 捕获缓冲区不会从一个正则表达式匹配到下一个(如果您的程序使用多个正则表达式),但它会在单个正则表达式中保持设置,直到它被其捕获组的另一次执行覆盖或直到执行设置它是回溯的。它的行为就像一种动态范围的变量,对其整个模式都是全局的。
  • 老鼠...我现在看到了。整个模式用+ 量化。因此,第一个 one 位于 \2onetwo +1 一起使用。
猜你喜欢
  • 1970-01-01
  • 2011-03-20
  • 1970-01-01
  • 1970-01-01
  • 2011-09-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-05
相关资源
最近更新 更多