这是正则表达式:
([A-Z]+(?:(?:[\w\d@#$%&;,\+\.\*!-]+)?\s?(?![a-z&;]+\s)){1,})\s(<span class="label label-inverse">.*?</span>)
这将匹配如下字符串:
<p>Buy Apple <span class="label label-inverse">AAPL - NYSE</span> at or under $100 per share.</p>
在javascript正则表达式测试程序(如regexpal)中测试时,它可以按预期工作。但是,PHP preg_replace函数返回null,错误为PREG_BACKTRACK_LIMIT_ERROR。
$string = preg_replace('~([A-Z]+(?:(?:[\w\d@#%&!;,\+\.\*\$-]+)?\s?(?![a-z&;]+\s)){1,})\s(<span class="label label-inverse">.*?</span>)~i', '<strong>$1</strong> $2', $string);
这是为什么?任何人都可以解释PHP中的正则表达式有什么问题,以及如何纠正它,以便它像在javascript中一样运行?
答案 0 :(得分:0)
这是一个丑陋的表达。你听说过用正则表达式解析html的警告,对吧?
{1,}
可以替换为+
[\w\d@#$%&;,\+\.\*!-]
可以替换为[\w@#$%&;,+.*!-]
(?:... +)?
中的量词可以替换为*
坦率地说,我没有理由不将其简化为:
([A-Z]+[\w@#$%&;,+.*!\s-]+)\s(<span class="label label-inverse">.*?</span>)
甚至更进一步。
在the demo中,查看右侧窗格中的捕获组。
答案 1 :(得分:0)
回溯限制通常是由于表达效率低下造成的;你应该简化它:
~([\w\s\d@#$%&;,+.*!-]+)(?=<span class="label label-inverse">[^<]+</span>)~i'
如果后跟<span>
标记,它会捕获一个单词(或多个单词);未捕获前瞻断言,因此它使替换模式更简单。
$expr = '~([\w\s\d@#$%&;,+.*!-]+)(?=<span class="label label-inverse">[^<]+</span>)~i';
$string = preg_replace($expr, '<strong>$1</strong>', $string);
似乎规则可以描述为:
<span>
<span>
所以:
~((?:[A-Z]\S*\s)+|\S+\s)(?=<span class="label label-inverse">[^<]+</span>)~