<p><code>MIS Notes:.*(//p//)?.*</code>的工作原理是这样的,在{<cd2>}作为目标的例子中:</p>
<ol>
<li><code>MIS Notes:</code>匹配<code>"MIS Notes:"</code>,这里没有什么惊喜。在</li>
<li><code>.*</code>立即运行到字符串的末尾(到目前为止匹配<code>"MIS Notes: //p//"</code>)</li>
<li><code>(//p//)?</code>是可选的。什么也没发生。在</li>
<li><code>.*</code>没有可匹配的内容,我们已经在字符串的末尾了。由于star允许前一个原子的匹配项为零,因此regex引擎停止将整个字符串报告为匹配项,并将子组报告为空。在</li>
</ol>
<p>现在,当您将regex更改为<code>MIS Notes:.*(//p//).*</code>时,行为将发生变化:</p>
<ol>
<li><code>MIS Notes:</code>匹配<code>"MIS Notes:"</code>,这里仍然没有惊喜。在</li>
<li><code>.*</code>立即运行到字符串的末尾(到目前为止匹配<code>"MIS Notes: //p//"</code>)</li>
<li><code>(//p//)</code>是必需的。为了满足这一要求,引擎开始逐字回溯。(目前为止匹配<code>"MIS Notes: "</code>)</li>
<li><code>(//p//)</code>可以匹配。子组1被保存并包含<code>"//p//"</code>。在</li>
<li><code>.*</code>运行到字符串的末尾。提示:如果您对它匹配的内容不感兴趣,那么它是多余的,您可以删除它。在</li>
</ol>
<p>现在,当您将regex更改为<code>MIS Notes:.*?//(p)//</code>时,行为将再次更改:</p>
<ol>
<li><code>MIS Notes:</code>匹配<code>"MIS Notes:"</code>,这里仍然没有惊喜。在</li>
<li><code>.*?</code>是非贪心的,在它继续之前检查以下原子(match-to-to <code>"MIS Notes: "</code>)</li>
<li><code>//(p)//</code>可以匹配。子组1被保存并包含<code>"p"</code>。在</li>
<li>完成了。请注意,不会发生回溯,这样可以节省时间。在</li>
</ol>
<p>现在,如果您知道在<code>//p//</code>之前不能有<code>/</code>,那么可以使用:<code>MIS Notes:[^/]*//(p)//</code>:</p>
<ol>
<li><code>MIS Notes:</code>匹配<code>"MIS Notes:"</code>,你明白了。在</li>
<li><code>[^/]*</code>可以快进到第一个斜杠(这比<code>.*?</code>快)</li>
<li><code>//(p)//</code>可以匹配。子组1被保存并包含<code>"p"</code>。在</li>
<li>完成了。请注意,不会发生回溯,这样可以节省时间。这应该比版本3快。在</li>
</ol>