<p>灾难性回溯问题的一个有效解决方案是,通过对捕获组使用正向前瞻来模拟<a href="https://www.rexegg.com/regex-disambiguation.html#atomic" rel="nofollow noreferrer">atomic group</a>(Python的<code>re</code>模块不支持):</p>
<pre><code>(?=((?:[a-z]+\.?\s*)+))\1§{0,2}\s*\d+
</code></pre>
<p>设置了多行和大小写无关标志。这避免了灾难性的回溯,因为前瞻不会放弃角色</p>
<p><a href="https://regex101.com/r/icHjRR/2/" rel="nofollow noreferrer">Demo</a></p>
<p>更简洁的方法是在匹配一个或多个字母时使用<a href="https://www.rexegg.com/regex-quantifiers.html#possessive" rel="nofollow noreferrer">possessive quantifier</a>。可以使用正则表达式</p>
<pre><code>(?:[a-z]++\.?\s*)+§{0,2}\s*\d+
</code></pre>
<p>设置了多行和大小写无关标志。这里所有格修饰语由<code>++</code>表示</p>
<p><a href="https://regex101.com/r/icHjRR/1/" rel="nofollow noreferrer">Demo</a></p>
<p>不幸的是,Python的<code>re</code>模块不支持所有格修饰符,但它的替代<a href="https://pypi.org/project/regex/" rel="nofollow noreferrer">PyPi module</a>支持所有格修饰符</p>
<p>假设我们使用了regex<code>(?:[a-z]+\.?\s*)+§{0,2}\s*\d+</code>,它没有所有格修饰语</p>
<p>对于字符串</p>
<pre><code>Within the Context. of Article 1A(2)
</code></pre>
<p><code>[a-z]+</code>匹配<code>Within the Context</code>,然后<code>\.?\s*</code>匹配<code>.</code>。然后,正则表达式引擎继续尝试查找整个正则表达式的匹配项。如果失败,它将回溯考虑替代方案,并可能返回到{{CD5}}的匹配,此时它将<eEM>返回“EEM>字符{{CD10}}(使匹配^ {CD11}}),在R{CD10}}之前重置ReGEX引擎的内部指针,并再次继续前进。<p>
<p>中的所有格修饰符<code>++</code>防止正则表达式引擎放弃其原始匹配<code>Within the Context</code>中的任何字符,从而避免灾难性的回溯问题。即使在灾难性回溯不是问题的地方,所有格修饰语也可以大大提高效率</p>