这个前向正则表达式示例如何工作?

时间:2017-12-23 10:22:42

标签: regex

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

  

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

因此“/ 2”失败的事实意味着跳过了以下“两个”?

  

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

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

  

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

这个例子来自这里:

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

1 个答案:

答案 0 :(得分:3)

(\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

^第二次迭代后。