(\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
^ 第二次迭代后。