PHP preg_replace has error. How can I found out the reason?

时间:2018-09-18 20:29:26

标签: php regex preg-replace

$string = '## aaa                                                                 bbb';
$pattern = '/^(\n)?\s{0,}#{1,6}\s+| {0,}(\n)?\s{0,}#{0,} {0,}(\n)?\s{0,}$/';
$replacement = '$1$2$3';
echo preg_replace($pattern, $replacement, $string);

If the space between "aaa" and "bbb" is around 50 (or less), I DO get the correct result. BUT if I increase the number, say there are 100 space between "aaa" and "bbb". I get null. How can I find out the reason?

1 个答案:

答案 0 :(得分:1)

该模式匹配两个替代方案,一个^(\n)?\s*#{1,6}\s+和另一个 *(\n)?\s*#* *(\n)?\s*$

第一个可以,尽管建议将\n设为可选,而不是将整个组设为可选。

第二个模式 *(\n)?\s*#* *(\n)?\s*$是非常低效的模式,因为有\s*个模式跟随可选的\n模式,而该模式又以 *开头图案。当没有\n时,\s*可能会“落入” *,并且leads to catastrophical backtracking会与部分模式匹配但最终子模式失败。

因此,您可以使用

/^(\n?)\s*#{1,6}\s+| *(?:(\n)\s*)?#* *(?:(\n)\s*)?$/

请参见regex demo

此处的关键点是(?:(\n)\s*)?个部分,其中\n是必需的,只有在所有常规空格都与 *然后匹配{{ 1}}仅在之前有\s*时才会尝试,这样可以确保没有子模式落入另一个模式中。